Ver Mensaje Individual
  #2 (permalink)  
Antiguo 11/05/2016, 11:39
Avatar de xKuZz
xKuZz
 
Fecha de Ingreso: febrero-2015
Ubicación: nullptr
Mensajes: 183
Antigüedad: 9 años, 9 meses
Puntos: 27
Respuesta: Saber todas las combinaciones posibles de un tablero

Para resolver problemas de este tipo hay muchas técnicas variadas de búsqueda en espacio de estados que dan solución al problema (búsquedas en anchura, profundidad, algoritmos genéticos) o técnicas algorítmicas de backtracking o branch & bound suelen ser útiles. Probablemente backtracking sea la más apropiada para el problema.

No obstante, el número de tableros posibles para 4 fichas si consideramos una representación con un vector de 4 enteros en el que el índice es la fila y el valor es la columna y en los valores aparece cada valor del 1 al 4 una única vez se reduce a comprobar todas las permutaciones de esos cuatro números y determinar cuáles son factibles, y 4! = 4 * 3 * 2 = 24 tableros se comprueba en un momentillo. Por tanto hacerlo por fuerza bruta no es ningún problema. En C++:

Código C++:
Ver original
  1. #include <algorithm>
  2. #include <iostream>
  3. #include <set>
  4. #include <tuple>
  5. #include <vector>
  6.  
  7. using namespace std;
  8.  
  9. bool esFactible(const vector<int>& fichas) {
  10.     set<int> diagonal_descendente;
  11.     set<int> diagonal_ascendente;
  12.     bool unico = true;
  13.     for (unsigned i = 0; i < fichas.size(); ++i) {
  14.         // Si dos valores fila - columna coinciden indican que estamos en
  15.         // la misma diagonal descendente
  16.         tie(ignore, unico) =diagonal_descendente.insert(i-fichas[i]);
  17.         if (!unico)
  18.             return false;
  19.  
  20.         // Si dos valores fila + columna coinciden indican que estamos en
  21.         // la misma diagonal ascendente
  22.         tie(ignore, unico) = diagonal_ascendente.insert(i+fichas[i]);
  23.         if (!unico)
  24.             return false;
  25.     }
  26.  
  27.     // Si no ocurre nada de eso es una solución porque no hay encuentros
  28.     // diagonales y la modelización del espacio de estados evita que haya
  29.     // columnas o filas iguales
  30.     return true;
  31. }
  32.  
  33. int main() {
  34.     // Representación del tablero
  35.     // Índice -> Filas -1
  36.     // Valor -> Columnas
  37.     vector<int> fichas {1, 2, 3, 4};
  38.  
  39.     // A permutar
  40.     do {
  41.         if (esFactible(fichas)) {
  42.             cout << "SOLUCION" << endl;
  43.             for (unsigned i = 0; i < fichas.size(); ++i)
  44.                 cout << "Fila " << i+1 << "\t Columna" << fichas[i] << endl;
  45.             cout << endl << endl;
  46.         }
  47.     } while (next_permutation(fichas.begin(),fichas.end()));
  48.  
  49. }
Que me devuelve como solución dos únicos tableros que cumplen eso si no lo he hecho mal que creo que no.

Fila 1 Columna2
Fila 2 Columna4
Fila 3 Columna1
Fila 4 Columna3


SOLUCION
Fila 1 Columna3
Fila 2 Columna1
Fila 3 Columna4
Fila 4 Columna2

Hay un problema muy similar a este que es el problema de las 8 reinas y que se resolvería de la misma manera (eso sí la fuerza bruta cuanto más grande es el tablero menos recomendable). Infórmate sobre éstos que te he comentado y te dará para rato y una manera de encontrar la solución más apropiada que comprobarlo todo y aunque este problema haya sido resuelto aquí con esta fuerza bruta cutre la búsqueda en el espacio de estados en un tema denso e interesante si te gustan este tipo de problemas.