为每个状态定义两个函数S和H,分别表示当前状态到列一致和行一致的目标状态的最少操作次数。
然后有了估价函数F=Min(S,H)就可以IDA*了。
#include <cstdio> #include <iostream> #include <fstream> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <queue> #define rep(i, l, r) for(int i=l; i<=r; i++) #define down(i, l, r) for(int i=l; i>=r; i--) #define maxn 40320 #define MAX 1<<30 using namespace std; int t, n[5][5], k; inline void Up(int x) { int a; a = n[1][x]; n[1][x] = n[2][x]; n[2][x] = n[3][x]; n[3][x] = n[4][x]; n[4][x] = a; } inline void Down(int x) { int a; a = n[4][x]; n[4][x] = n[3][x]; n[3][x] = n[2][x]; n[2][x] = n[1][x]; n[1][x] = a; } inline void Right(int x) { int a; a = n[x][4]; n[x][4] = n[x][3]; n[x][3] = n[x][2]; n[x][2] = n[x][1]; n[x][1] = a; } inline void Left(int x) { int a; a = n[x][1]; n[x][1] = n[x][2]; n[x][2] = n[x][3]; n[x][3] = n[x][4]; n[x][4] = a; } int S() { int b[5], o, o2 = 0; rep(i, 1, 4) { rep(j, 1, 4) b[j] = 0; o = 0; rep(j, 1, 4) b[n[j][i]]++; rep(j, 1, 4) o = max(o, b[j]); o2 = max(o2, 4-o); } return o2; } int H() { int b[5], o, o2 = 0; rep(i, 1, 4) { rep(j, 1, 4) b[j] = 0; o = 0; rep(j, 1, 4) b[n[i][j]]++; rep(j, 1, 4) o = max(o, b[j]); o2 = max(o2, 4-o); } return o2; } bool Search(int x) { if (x == k) { if (!S() || !H()) return true; else return false; } int now = min(S(), H()); if (now > k-x) return false; Left(1); if (min(S(), H()) <= now) if (Search(x+1)) return true; Right(1); Left(2); if (min(S(), H()) <= now) if (Search(x+1)) return true; Right(2); Left(3); if (min(S(), H()) <= now) if (Search(x+1)) return true; Right(3); Left(4); if (min(S(), H()) <= now) if (Search(x+1)) return true; Right(4); Right(1); if (min(S(), H()) <= now) if (Search(x+1)) return true; Left(1); Right(2); if (min(S(), H()) <= now) if (Search(x+1)) return true; Left(2); Right(3); if (min(S(), H()) <= now) if (Search(x+1)) return true; Left(3); Right(4); if (min(S(), H()) <= now) if (Search(x+1)) return true; Left(4); Up(1); if (min(S(), H()) <= now) if (Search(x+1)) return true; Down(1); Up(2); if (min(S(), H()) <= now) if (Search(x+1)) return true; Down(2); Up(3); if (min(S(), H()) <= now) if (Search(x+1)) return true; Down(3); Up(4); if (min(S(), H()) <= now) if (Search(x+1)) return true; Down(4); Down(1); if (min(S(), H()) <= now) if (Search(x+1)) return true; Up(1); Down(2); if (min(S(), H()) <= now) if (Search(x+1)) return true; Up(2); Down(3); if (min(S(), H()) <= now) if (Search(x+1)) return true; Up(3); Down(4); if (min(S(), H()) <= now) if (Search(x+1)) return true; Up(4); return false; } int main() { scanf("%d", &t); while (t--) { rep(i, 1, 4) rep(j, 1, 4) scanf("%d", &n[i][j]); k = 0; while (k <= 5) if (Search(0)) break; else k++; if (k == 6) k = -1; printf("%d ", k); } return 0; }