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;
}