poj 1077 zoj 1217 hdu 1043 八数码
题意:以sample为例
将 2 3 4 1 2 3
1 5 x —> 4 5 6
7 6 8 7 8 x
x可以与上下左右交换,问最少的交换次数到达
上例的答案是: ullddrurdllurdruldr
不过我程序运行的答案是:ullddrurdllurrdlurd
虽然结果不同,但是答案也是正确的,因为只要输出一个路径
下面说一下我的做法:
我将3*3的矩阵压缩成一个数,x用0表示,状态总共有9!=362880种,我用一个数组记录,查找时用二分查找,(刚刚华爷(搜索神牛)告诉我只要hash mod1000007
刚刚好所有的数字都不会有重合的,这就是八数码一个神奇的地方,大家可以去试试)
用bfs从123456780 扩展下去->123450786和123456708,直到队列空为止,记得要记录路径。
1077 | Accepted | 14116K | 391MS | G++ | 3147B |
Accepted | 1217 | C++ | 220 | 16068 |
Accepted | 1043 | 125MS | 14360K | 3331 B | C++ |
看来hdu的服务器是最快的
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define N 1000000
const int n = 9;
int memory[N],top;
int a[n],b[n],p[n];
int maze[n+1][n+1];
void init()
{
top=0;
p[0] = 1;
for(int i=1;i<n;i++) p[i] = p[i-1] * 10;
b[n-1] = 1;
for(int i=n-2;i>=0;i--) b[i] = b[i+1] *10;
for(int i=0;i<n;i++) a[i] = i;
do
{
int sum=0;
for(int i=0;i<n;i++) sum += a[i]*b[i];
memory[top++] = sum;
}while(next_permutation(a,a+n));
memset(maze,0,sizeof(maze));
for(int i=1;i<=3;i++)
for(int j=1;j<=3;j++)
maze[i][j]=1;
}
struct node
{
int to,turn;
}path[N];
int mark[N];
struct info
{
int x,index,pos;
};
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};
int ad[]={-3,1,3,-1};
int pu[]={3,-1,-3,1};
int turnx[] = {1,1,1,2,2,2,3,3,3};
int turny[] = {1,2,3,1,2,3,1,2,3};
int turn(int k,int index,int x)
{
int ret;
int x1,x2;
x1 = x/b[index]%10;
x2 = x/b[index+ad[k]]%10;
ret = x - x1*b[index] - x2*b[index+ad[k]] + x1*b[index+ad[k]] + x2*b[index];
return ret;
}
int ll;
void bfs()
{
memset(path,-1,sizeof(path));
memset(mark,0,sizeof(mark));
queue<struct info> q;
struct info tmp1,tmp2;
int l,r,sum = 0;
for(int i=1;i<n;i++) sum += i*b[i-1];
tmp1.x = sum; tmp1.index = 8;
ll=l = lower_bound(memory,memory+top,sum) - memory;
tmp1.pos=l;
mark[l] = 1;
q.push(tmp1);
while(!q.empty())
{
tmp1 = q.front();
q.pop();
int xx = turnx[tmp1.index], yy = turny[tmp1.index];
for(int k=0;k<4;k++)
{
int x = xx +dx[k],y = yy + dy[k];
if(maze[x][y])
{
tmp2.x = turn(k,tmp1.index ,tmp1.x);
l = lower_bound(memory,memory+top,tmp2.x)-memory;
if(mark[l]==0)
{
tmp2.index = tmp1.index + ad[k];
tmp2.pos = l;
path[l].turn = k;
path[l].to = tmp1.pos;
q.push(tmp2);
mark[l] = 1;
}
}
}
}
}
int main()
{
// freopen("in","r",stdin);
init();
bfs();
int sum=0,l;
char ch;
while(cin>>ch)
{
if(ch!='x') sum = (ch-'0')*b[0];
else sum = 0;
for(int i=1;i<n;i++)
{
cin>>ch;
if(ch == 'x') continue;
sum += (ch - '0') * b[i];
}
l = lower_bound(memory,memory+top,sum) - memory;
if(mark[l]==0) printf("unsolvable");
else
{
while(l!=ll)
{
if(path[l].turn==0) putchar('d');
else if(path[l].turn==1) putchar('l');
else if(path[l].turn==2) putchar('u');
else putchar('r');
l=path[l].to;
}
}
printf("\n");
}
return 0;
}