题目
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3814
分析
可以发现对于两个相邻的格子并且他们相邻的边都是有锯齿的,那么他们的旋转的。进一步可以得知他们的影响关系如果出现循环也不会有矛盾,因此可以简单模拟旋转过程。
易知每个格子最多有四种状态,我们可以用4^9来表示所有的状态,然后暴力搜索,模拟其中的旋转过程就可以了。
注意一个地方,就是目标状态的判断。因为不同状态表示的实际格子状态可能是相同的,对目标状态九个格子要分别判断哪些压缩后的状态是合法的,只要出现一种合法状态就找到了解。
代码
#include<cstring> #include<string> #include<cstdio> #include<cstdlib> #include<iostream> #include<vector> #include<algorithm> #include<cmath> #include<queue> using namespace std; #define ll long long #define pf printf #define sf scanf #define Fill(a,b) memset(a,b,sizeof(a)) struct State { int st[11]; State(){} State(int a1,int a2,int a3,int a4,int a5,int a6,int a7,int a8,int a9) { st[1] = a1; st[2] = a2; st[3] = a3; st[4] = a4; st[5] = a5; st[6] = a6; st[7] = a7; st[8] = a8; st[9] = a9; } }; queue<State>q; string s[10][10],t[10][10],p[10]; int st[11][11]; int tp[5][5]; bool sol[11]; bool cor[11][11]; int f[1 << 20]; int ans; const int up[] = {0,0,0,0,1,2,3,4,5,6}; const int down[] = {0,4,5,6,7,8,9,0,0,0}; const int lef[] = {0,0,1,2,0,4,5,0,7,8}; const int rig[] = {0,2,3,0,5,6,0,8,9,0}; inline void Init_initial() { for (int i = 1; i <= 8; i++) for (int j = 1; j <= 3; j++) cin>>s[j][i]; for (int i = 1; i <= 8; i++) for (int j = 4; j <= 6; j++) cin>>s[j][i]; for (int i = 1; i <= 8; i++) for (int j = 7; j <= 9; j++) cin>>s[j][i]; } inline void Init_target() { for (int i = 1; i <= 8; i++) for (int j = 1; j <= 3; j++) cin>>t[j][i]; for (int i = 1; i <= 8; i++) for (int j = 4; j <= 6; j++) cin>>t[j][i]; for (int i = 1; i <= 8; i++) for (int j = 7; j <= 9; j++) cin>>t[j][i]; } inline int trans(State x) { int ans = 0; for (int i = 1; i <= 9; i++) ans = ans + (x.st[i] << (2 * (i - 1))); return ans; } inline bool meshed(State x,int a,int e1,int b,int e2) { int f1 = st[a][tp[x.st[a]][e1]],f2 = st[b][tp[x.st[b]][e2]]; return (f1 == 1 && f2 == 1); } inline State rotate(State x,int y,int flag) { sol[y] = 1; int l = lef[y],r = rig[y],u = up[y],d = down[y]; bool fl = 0,fu = 0,fd = 0,fr = 0; if (l != 0 && !sol[l] && meshed(x,l,3,y,1)) fl = 1; if (r != 0 && !sol[r] && meshed(x,r,1,y,3)) fr = 1; if (u != 0 && !sol[u] && meshed(x,u,4,y,2)) fu = 1; if (d != 0 && !sol[d] && meshed(x,d,2,y,4)) fd = 1; int z = x.st[y]; if (flag == 1) { z = z + 1; if (z == 4) z = 0; } else { z = z - 1; if (z == -1) z = 3; } x.st[y] = z; if (fl && !sol[l]) { sol[l] = 1; x = rotate(x,l,3 - flag); } if (fr && !sol[r]) { sol[r] = 1; x = rotate(x,r,3 - flag); } if (fu && !sol[u]) { sol[u] = 1; x = rotate(x,u,3 - flag); } if (fd && !sol[d]) { sol[d] = 1; x = rotate(x,d,3 - flag); } return x; } inline bool ok(State y) { for (int i = 1; i <= 9; i++) if (!cor[i][y.st[i]]) return 0; return 1; } inline void bfs(State x) { while (!q.empty()) q.pop(); q.push(x); while (!q.empty()) { x = q.front(); q.pop(); int sx = trans(x); for (int i = 1; i <= 9; i++) { Fill(sol,0); State y = rotate(x,i,1); int sy = trans(y); if (f[sy] > f[sx] + 1) { f[sy] = f[sx] + 1; if (ok(y)) { ans = f[sy]; return; } q.push(y); } } } } inline bool same(int x) { for (int i = 1; i <= 8; i++) for (int j = 0; j < 8; j++) if (s[x][i][j] != t[x][i][j]) return 0; return 1; } inline void change(int x) { for (int i = 1; i <= 8; i++) p[i] = ""; for (int i = 1; i <= 8; i++) for (int j = 8; j >= 1; j--) p[i] = p[i] + s[x][j][i - 1]; for (int i = 1; i <= 8; i++) s[x][i] = p[i]; } int main() { // freopen("in.txt","r",stdin); int T; sf("%d",&T); for (int TT = 1; TT <= T; TT++) { Init_initial(); Init_target(); for (int i = 1; i <= 9; i++) for (int j = 1; j <= 4; j++) sf("%d",&st[i][j]); Fill(f,63); tp[0][1] = 1; tp[0][2] = 2; tp[0][3] = 3; tp[0][4] = 4; tp[1][1] = 4; tp[1][2] = 1; tp[1][3] = 2; tp[1][4] = 3; tp[2][1] = 3; tp[2][2] = 4; tp[2][3] = 1; tp[2][4] = 2; tp[3][1] = 2; tp[3][2] = 3; tp[3][3] = 4; tp[3][4] = 1; f[0] = 0; ans = -1; Fill(cor,0); for (int i = 1; i <= 9; i++) for (int j = 0; j < 4; j++) { if (same(i)) cor[i][j] =1; change(i); } bfs(State(0,0,0,0,0,0,0,0,0)); pf("%d\n",ans); } return 0; }