sto cercando di risolvere il seguente problema:ordine griglia 3x3 da 2x2 ruotando subgrids
Data una griglia 3x3 con i numeri 1-9, ad esempio:
2 8 3
1 4 5
7 9 6
devo ordinare la griglia ruotando una subgrid 2x2 in senso orario o antiorario. L'esempio di cui sopra potrebbe essere risolto in questo modo:
Ruotare la parte superiore sinistra piece senso orario:
2 8 3 1 2 3
1 4 5 => 4 8 5
7 9 6 7 9 6
ruotare la parte inferiore destra piece antiorario:
1 2 3 1 2 3
4 8 5 => 4 5 6
7 9 6 7 8 9
La griglia è ora 'ordinato' .
Questo è un compito a casa, ma non sto ottenendo questo. Forza brutale non ha funzionato; Devo essere in grado di risolvere tutte le griglie date in < = 2000ms. Una cosa che ho provato è stata cercare di calcolare un valore per tutte le 8 possibili mosse successive (ruotare tutti e 4 i pezzi in entrambe le direzioni), quindi ruotare il pezzo con il valore migliore. Questo valore è stato calcolato sommando tutte le distanze di tutti i numeri dalle loro posizioni corrette.
Questo ha funzionato per l'esempio precedente, ma quelli più difficili sono un no-go.
Qualcuno potrebbe indicarmi la direzione corretta? Dove dovrei iniziare? Questo problema ha un nome?
Tutte le griglie sono 3x3 e le parti rotanti sono sempre 2x2.
Grazie in anticipo.
MODIFICA: Ho dimenticato di menzionare la cosa più grande: devo trovare la più piccola quantità possibile di curve che ordinano la griglia.
EDIT2:
ho implementato un algoritmo di lavorare con piccoli consigli da tutto il suggerimento che ho ricevuto. La cosa fastidiosa è che sulla mia macchina viene eseguito lo scenario peggiore (987654321) in 1,5 secondi, ma sul server che esegue il test del programma viene eseguito> 2s, il che significa che devo ancora ottimizzare. Il mio codice di lavoro com'è ora
Qualcuno può venire con qualche consiglio di ottimizzazione?
Edit3:
Un'implementazione dal look-up table un'idea di Sirko, come ho capito:
import java.util.*;
class Permutation {
String str;
int stage;
public Permutation(String str, int stage) {
this.str = str;
this.stage = stage;
}
}
public class Kiertopeli {
// initialize the look-up table
public static Map<String, Integer> lookUp = createLookup();
public static int etsiLyhin(int[][] grid) {
String finale = "";
for(int[] row : grid)
for(int num : row)
finale += Integer.toString(num);
// fetch the wanted situation from the look-up table
return lookUp.get(finale);
}
public static Map<String, Integer> createLookup() {
// will hold the list of permutations we have already visited.
Map<String, Integer> visited = new HashMap<String, Integer>();
Queue<Permutation> q = new ArrayDeque<Permutation>();
q.add(new Permutation("123456789", 0));
// just for counting. should always result in 362880.
int permutations = 0;
Permutation permutation;
creation:
while(!q.isEmpty())
{
permutation = q.poll();
// pick the next non-visited permutation.
while(visited.containsKey(permutation.str)) {
if(q.isEmpty()) break creation;
permutation = q.poll();
}
// mark the permutation as visited.
visited.put(permutation.str, permutation.stage);
// loop through all the rotations.
for(int i = 0; i < 4; i++) {
// get a String array with arr[0] being the permutation with clockwise rotation,
// and arr[1] with counter-clockwise rotation.
String[] rotated = rotate(permutation.str, i);
// if the generated permutations haven't been created before, add them to the queue.
if(!visited.containsKey(rotated[0])) q.add(new Permutation(rotated[0], permutation.stage+1));
if(!visited.containsKey(rotated[1])) q.add(new Permutation(rotated[1], permutation.stage+1));
}
permutations++;
}
System.out.println(permutations);
return visited;
}
public static String[] rotate(String string, int place) {
StringBuilder str1 = new StringBuilder(string);
StringBuilder str2 = new StringBuilder(string);
if(place == 0) { // top left piece
str1.setCharAt(0, string.charAt(3));
str1.setCharAt(1, string.charAt(0)); // clockwise rotation
str1.setCharAt(4, string.charAt(1)); //
str1.setCharAt(3, string.charAt(4));
str2.setCharAt(3, string.charAt(0));
str2.setCharAt(0, string.charAt(1)); // counter-clockwise
str2.setCharAt(1, string.charAt(4)); //
str2.setCharAt(4, string.charAt(3));
}
if(place == 1) { // top right
str1.setCharAt(1, string.charAt(4));
str1.setCharAt(2, string.charAt(1));
str1.setCharAt(5, string.charAt(2));
str1.setCharAt(4, string.charAt(5));
str2.setCharAt(4, string.charAt(1));
str2.setCharAt(1, string.charAt(2));
str2.setCharAt(2, string.charAt(5));
str2.setCharAt(5, string.charAt(4));
}
if(place == 2) { // bottom left
str1.setCharAt(3, string.charAt(6));
str1.setCharAt(4, string.charAt(3));
str1.setCharAt(7, string.charAt(4));
str1.setCharAt(6, string.charAt(7));
str2.setCharAt(6, string.charAt(3));
str2.setCharAt(3, string.charAt(4));
str2.setCharAt(4, string.charAt(7));
str2.setCharAt(7, string.charAt(6));
}
if(place == 3) { // bottom left
str1.setCharAt(4, string.charAt(7));
str1.setCharAt(5, string.charAt(4));
str1.setCharAt(8, string.charAt(5));
str1.setCharAt(7, string.charAt(8));
str2.setCharAt(7, string.charAt(4));
str2.setCharAt(4, string.charAt(5));
str2.setCharAt(5, string.charAt(8));
str2.setCharAt(8, string.charAt(7));
}
return new String[] { str1.toString(), str2.toString() };
}
public static void main(String[] args) {
String grids = "2 8 3 1 4 5 7 9 6 "
+ "1 6 5 8 7 2 3 4 9 "
+ "1 6 5 8 7 2 3 4 9 "
+ "1 7 6 8 2 5 3 4 9 "
+ "8 1 5 7 4 6 3 9 2 "
+ "9 8 7 6 5 4 3 2 1 ";
Scanner reader = new Scanner(grids);
System.out.println();
while (reader.hasNext()) {
System.out.println("Enter grid:");
int[][] grid = new int[3][3];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
grid[i][j] = reader.nextInt();
}
}
System.out.println(" Smallest: " + etsiLyhin(grid));
}
}
}
corre per circa 1500-1600ms ogni volta.
EDIT4: Seguendo il consiglio di Sirko sono riuscito a ridurre i tempi di esecuzione a 600 ms. Ecco il codice come è ora:
import java.util.*;
class Permutation {
Byte[] value;
int stage;
public Permutation(Byte[] value, int stage) {
this.value = value;
this.stage = stage;
}
public Byte[][] rotate(int place) {
Byte[] code1 = value.clone();
Byte[] code2 = value.clone();
if(place == 0) { // top left piece
code1[0] = value[3];
code1[1] = value[0];
code1[4] = value[1];
code1[3] = value[4];
code2[3] = value[0];
code2[0] = value[1];
code2[1] = value[4];
code2[4] = value[3];
}
if(place == 1) { // top right
code1[1] = value[4];
code1[2] = value[1];
code1[5] = value[2];
code1[4] = value[5];
code2[4] = value[1];
code2[1] = value[2];
code2[2] = value[5];
code2[5] = value[4];
}
if(place == 2) { // bottom left
code1[3] = value[6];
code1[4] = value[3];
code1[7] = value[4];
code1[6] = value[7];
code2[6] = value[3];
code2[3] = value[4];
code2[4] = value[7];
code2[7] = value[6];
}
if(place == 3) { // bottom left
code1[4] = value[7];
code1[5] = value[4];
code1[8] = value[5];
code1[7] = value[8];
code2[7] = value[4];
code2[4] = value[5];
code2[5] = value[8];
code2[8] = value[7];
}
return new Byte[][] { code1, code2 };
}
public Integer toInt() {
Integer ival = value[8] * 1 +
value[7] * 10 +
value[6] * 100 +
value[5] * 1000 +
value[4] * 10000 +
value[3] * 100000 +
value[2] * 1000000 +
value[1] * 10000000 +
value[0] * 100000000;
return ival;
}
}
public class Kiertopeli {
// initialize the look-up table
public static Map<Integer, Integer> lookUp = createLookup();
public static int etsiLyhin(int[][] grid) {
Integer finale = toInt(grid);
// fetch the wanted situation from the look-up table
return lookUp.get(finale);
}
public static Map<Integer, Integer> createLookup() {
// will hold the list of permutations we have already visited.
Map<Integer, Integer> visited = new HashMap<Integer, Integer>();
Map<Integer, Boolean> queued = new HashMap<Integer, Boolean>();
Queue<Permutation> q = new ArrayDeque<Permutation>();
q.add(new Permutation(new Byte[] { 1,2,3,4,5,6,7,8,9 }, 0));
queued.put(123456789, true);
// just for counting. should always result in 362880.
int permutations = 0;
Permutation permutation;
creation:
while(!q.isEmpty())
{
permutation = q.poll();
// pick the next non-visited permutation.
while(visited.containsKey(permutation.toInt())) {
if(q.isEmpty()) break creation;
permutation = q.poll();
}
// mark the permutation as visited.
visited.put(permutation.toInt(), permutation.stage);
// loop through all the rotations.
for(int i = 0; i < 4; i++) {
// get a String array with arr[0] being the permutation with clockwise rotation,
// and arr[1] with counter-clockwise rotation.
Byte[][] rotated = permutation.rotate(i);
// if the generated permutations haven't been created before, add them to the queue.
if(!visited.containsKey(toInt(rotated[0])) && !queued.containsKey(toInt(rotated[0]))) {
q.add(new Permutation(rotated[0], permutation.stage+1));
queued.put(toInt(rotated[0]), true);
}
if(!visited.containsKey(toInt(rotated[1])) && !queued.containsKey(toInt(rotated[1]))) {
q.add(new Permutation(rotated[1], permutation.stage+1));
queued.put(toInt(rotated[1]), true);
}
}
permutations++;
}
System.out.println(permutations);
return visited;
}
public static Integer toInt(Byte[] value) {
Integer ival = value[8] * 1 +
value[7] * 10 +
value[6] * 100 +
value[5] * 1000 +
value[4] * 10000 +
value[3] * 100000 +
value[2] * 1000000 +
value[1] * 10000000 +
value[0] * 100000000;
return ival;
}
public static Integer toInt(int[][] value) {
Integer ival = value[2][2] * 1 +
value[2][1] * 10 +
value[2][0] * 100 +
value[1][2] * 1000 +
value[1][1] * 10000 +
value[1][0] * 100000 +
value[0][2] * 1000000 +
value[0][1] * 10000000 +
value[0][0] * 100000000;
return ival;
}
public static void main(String[] args) {
String grids = "2 8 3 1 4 5 7 9 6 "
+ "1 6 5 8 7 2 3 4 9 "
+ "1 6 5 8 7 2 3 4 9 "
+ "1 7 6 8 2 5 3 4 9 "
+ "8 1 5 7 4 6 3 9 2 "
+ "9 8 7 6 5 4 3 2 1 ";
Scanner reader = new Scanner(grids);
System.out.println();
while (reader.hasNext()) {
System.out.println("Enter grid:");
int[][] grid = new int[3][3];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
grid[i][j] = reader.nextInt();
}
}
System.out.println(" Smallest: " + etsiLyhin(grid));
}
}
}
grazie enorme a Sirko e tutti gli altri che mi hanno dato suggerimenti, come pure!
fare tutti i numeri si verificano solo una volta? –
Sì. I numeri nella griglia sono sempre 1-9. Cioè, 1, 2, 3, 4, 5, 6, 7, 8 e 9 in un certo ordine. –
ok. Penso che cercherei sempre di trovare il valore minimo sempre e ruotarlo nella sua posizione corretta e poi continuare nella stessa materia. problema interessante, comincerà a risolvere: D –