poj 1077 zoj 1217 hdu 1043 八数码

来源:互联网 发布:婚庆域名 编辑:程序博客网 时间:2024/06/05 08:55

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,直到队列空为止,记得要记录路径。

 

1077Accepted14116K391MSG++3147B

 

 Accepted 1217C++22016068

 

Accepted1043125MS14360K3331 BC++

 

看来hdu的服务器是最快的

 

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>using namespace std;#define N 1000000const 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;}