bfs + 哈希技术,,,
超经典,超高效代码:::
#include <cstdio> #include <cstring> #define MAX 1000000 int ans, st[MAX][9], head[MAX], next[MAX], posi[MAX], fa[MAX], path[MAX]; int dx[4] = {-1,1,0,0}, dy[4] = {0,0,-1,1}; char dir[4] = {'U','D','L','R'}; int hash(int *A) { int v = 0; for(int i = 0; i < 9; i++) v = v * 10 + A[i]; return v%MAX; } int try_to_insert(int s) { int h = hash(st[s]); int u = head[h]; while(u) { if(memcmp(st[u], st[s],sizeof(st[s]))==0) return 0; u = next[u]; } next[s] = head[h]; head[h] = s; return 1; } void bfs(int p) { memset(head,0,sizeof(head)); memset(next,0,sizeof(head)); int rear = 0, front = 1; posi[0] = p; try_to_insert(0); while(rear<front) { int x = posi[rear]/3, y = posi[rear]%3; for(int i = 0; i < 4; i++) if(x+dx[i]>=0&&x+dx[i]<3&&y+dy[i]>=0&&y+dy[i]<3) { int op = posi[rear], np = (x+dx[i])*3+y+dy[i]; memcpy(st[front],st[rear],sizeof(st[rear])); st[front][op] = st[rear][np]; st[front][np] = st[rear][op]; if(try_to_insert(front)) { posi[front] = (x+dx[i])*3+y+dy[i]; fa[front] = rear; path[front] = i; front++; } } rear++; } ans = front-1; } void print_path(int cur) { if(cur) { print_path(fa[cur]); printf("%c",dir[path[cur]]); } } int main () { int t, p, cas = 0; scanf("%d",&t); while(t--) { for(int i = 0; i < 9; i++) { scanf("%d",&st[0][i]); if(st[0][i]==0) p = i;} bfs(p); printf("Puzzle #%d\n",++cas); for(int i = 0; i < 3; i++) { printf("%d %d %d", st[ans][3*i], st[ans][3*i+1], st[ans][3*i+2]); printf("\n"); } print_path(ans); printf("\n\n"); } return 0; }
还有编码方法。。就是9个数共有9!种排列,每一种排列都编上号,用vis数组来记录。。。。
代码如下:
#include <cstdio> #include <cstring> #define MAX 800000 int ans, st[MAX][9], vis[362880], posi[MAX], fa[MAX], path[MAX]; int dx[4] = {-1,1,0,0}, dy[4] = {0,0,-1,1}, fact[10] = {1,1,2,6,24,120,720,5040,40320,362880}; char dir[4] = {'U','D','L','R'}; int return_position(int s) { int code = 0; for(int i = 0, u = 0; i < 9; i++) { for(int j = i+1; j < 9; j++) if(st[s][i]>st[s][j]) u++; code+=fact[8-i]*u; u = 0; } return code; } void bfs(int p) { memset(vis,0,sizeof(vis)); int rear = 0, front = 1; posi[0] = p; while(rear<front) { int x = posi[rear]/3, y = posi[rear]%3; for(int i = 0; i < 4; i++) if(x+dx[i]>=0&&x+dx[i]<3&&y+dy[i]>=0&&y+dy[i]<3) { int op = posi[rear], np = (x+dx[i])*3+y+dy[i]; memcpy(st[front],st[rear],sizeof(st[rear])); st[front][op] = st[rear][np]; st[front][np] = st[rear][op]; if(!vis[return_position(front)]) { vis[return_position(front)] = 1; posi[front] = (x+dx[i])*3+y+dy[i]; fa[front] = rear; path[front] = i; front++; } } rear++; } ans = front-1; } void print_path(int cur) { if(cur) { print_path(fa[cur]); printf("%c",dir[path[cur]]); } } int main () { int t, p, cas = 0; scanf("%d",&t); while(t--) { for(int i = 0; i < 9; i++) { scanf("%d",&st[0][i]); if(st[0][i]==0) p = i;} bfs(p); printf("Puzzle #%d\n",++cas); for(int i = 0; i < 3; i++) { printf("%d %d %d", st[ans][3*i], st[ans][3*i+1], st[ans][3*i+2]); printf("\n"); } print_path(ans); printf("\n\n"); } return 0; }