和大多数ACMer一样,一开始,我习惯性的单项搜索,结果搞了一下午没搞出来,
看了人家的思路,我明白了单向搜16层是多么的可笑啊, 就算把数组开到最大也是不够用的。。。。
正确的做法应该是双向搜索
这样写了以后,我又呆了,还是不对,我忽略了逆向搜索输出路径是应该也是逆向的,就是说如果原来是逆向3搜过来的,输出是应该是输出3的逆向,就是1。
这是我做过搜索中少有的代码超长的题目,有点力不从心啊,
代码如下:
#include <cstdio> #include <cstring> #define MN 100003 using namespace std; int ok, ans, ans2, head[MN], next[MN], fa[MN], pa[MN], step[MN]; int back_st[MN][24], st[MN][24], sta[24], _aim[24] = {0,3,4,3,0,5,6,5,0,1,2,1,0,7,8,7,0,9,10,9,0}; int back_head[MN], back_next[MN], back_fa[MN], back_pa[MN]; int is_ok() { for(int i = 0; i < 21; i++) if(sta[i]!=_aim[i]) return 0; return 1; } int _strcmp(int *a, int *b) { for(int i = 0; i < 21; i++) if(a[i]!=b[i]) return 0; return 1; } int hash(int cur) { int s = 0; for(int i = 0; i < 2l; i++) s = (s * 11 + st[cur][i])%MN; return s; } int is_succeed(int cur) { int h = hash(cur); int u = back_head[h]; while(u) { if(_strcmp(back_st[u],st[cur])) { ans2 = u; return 1;} u = back_next[u]; } return 0; } int try_to_insert(int cur) { int h = hash(cur); int u = head[h]; while(u) { if(_strcmp(st[cur],st[u])) return 0; u = next[u]; } next[cur] = head[h]; head[h] = cur; return 1; } void bfs(int *A, int state) { int rear = 0, front = 1; step[0] = 0; for(int i = 0; i < 21; i++) st[0][i] = A[i]; memset(head,0,sizeof(head)); memset(next,0,sizeof(next)); try_to_insert(0); while(rear<front) { if(state>0&&is_succeed(rear)) { ok = 1; ans = rear; break; } if(step[rear]>8) break; for(int i = 0; i <= 9; i++) st[front][i+2] = st[rear][i]; st[front][0] = st[rear][10]; st[front][1] = st[rear][11]; for(int i = 12; i <= 20; i++) st[front][i] = st[rear][i]; if(try_to_insert(front)) {step[front] = step[rear]+1; pa[front] = 1; fa[front] = rear; front++;} for(int i = 9; i <= 18; i++) st[front][i] = st[rear][i+2]; st[front][19] = st[rear][9]; st[front][20] = st[rear][10]; for(int i = 0; i <= 8; i++) st[front][i] = st[rear][i]; if(try_to_insert(front)) {step[front] = step[rear]+1; pa[front] = 2; fa[front] = rear; front++;} for(int i = 0; i <= 9; i++) st[front][i] = st[rear][i+2]; st[front][10] = st[rear][0]; st[front][11] = st[rear][1]; for(int i = 12; i <= 20; i++) st[front][i] = st[rear][i]; if(try_to_insert(front)) {step[front] = step[rear]+1; pa[front] = 3; fa[front] = rear; front++;} for(int i = 9; i <= 18; i++) st[front][i+2] = st[rear][i]; st[front][9] = st[rear][19]; st[front][10] = st[rear][20]; for(int i = 0; i <= 8; i++) st[front][i] = st[rear][i]; if(try_to_insert(front)) {step[front] = step[rear]+1; pa[front] = 4; fa[front] = rear; front++;} rear++; } } void print_path(int cur) { if(!cur) return; print_path(fa[cur]); printf("%d",pa[cur]); } void back_print_path(int cur) { if(!cur) return; if(back_pa[cur]==1)printf("3"); else if(back_pa[cur]==3)printf("1"); else if(back_pa[cur]==2)printf("4"); else if(back_pa[cur]==4)printf("2"); back_print_path(back_fa[cur]); } int main () { int t; scanf("%d",&t); bfs(_aim,-1); memcpy(back_head,head,sizeof(head)); memcpy(back_next,next,sizeof(next)); memcpy(back_fa,fa,sizeof(fa)); memcpy(back_pa,pa,sizeof(pa)); memcpy(back_st,st,sizeof(st)); while(t--) { for(int i = 0; i < 24; i++) scanf("%d",&sta[i]); if(is_ok()) { puts("PUZZLE ALREADY SOLVED"); continue; } ans = ans2 = 0; ok = 0; bfs(sta,1); if(ok) { print_path(ans); back_print_path(ans2); printf("\n");} else puts("NO SOLUTION WAS FOUND IN 16 STEPS"); } return 0; }