恩。。。刚刚AC,心情是。。。。。。。“叫你作叫你作叫你作!!!!!!……………………”
其实。。。这一个代码真的DEBUG了很久我觉得。。。然后发现了如下问题,并且是我第二次再敲的时候还有同样的错误!!不知悔改啊啊啊。。。
第一个是在用map[hash]初始化的时候,我是定了-1为初值,原先为了鉴别初值,就没有改变init map的hash值,以为这样在输出路径的时候方便找出来。(不就是懒得改值嘛!)然后。。结果!!这样就等于初值的hash并没有使用过,于是在第一次DFS的时候,,初值又被纳入队列中了!!!!fuck!!!关键是。。第一次的时候被我在一个月黑风高的晚上发现了,然后debug完高高兴兴睡觉了,结果第二天完全忘记了错在哪里!!!!然后第二遍敲的时候就悲剧了!!!
第二个是要注意在算hash的时候要把x的状态也算进去。这样的状态才是完整的,不然肯定会出现冲突。
然后记得初始化,,,,,恩。。还有对于字符串这一类的题目,设计的样例一定要和题目的格式一样。。。这里坑了好久QAQ捂脸。
康托展开是对于全排列这一类的hash很有效,貌似不会出现冲突。但是个数要比较小,不然也容易爆。
对于A*算法,我觉得理解了BFS,就没什么问题了,只是加了一个条件而已。
话说这一题用g++居然跑的还快些。
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <queue>
using namespace std;
int f[9]={1,1,2,6,24,120,720,5040,40320};
int cmp[4][2]={0,1,0,-1,1,0,-1,0};
char tar[3][3]={'1','2','3','4','5','6','7','8','x'};
class node
{
public:
int x,y,h,g;
char map[5][5];
int hash;
friend bool operator < (const node &x,const node &y) //优先级必须是这样的,否则有错
{
if(x.h+x.g==y.g+y.h) return x.g>y.g;
return x.h+x.g>y.g+y.h;
}
void print()
{
printf("h=%d g=%d hash=%d\n",h,g,hash);
for(int i=0;i<3;i++) {for(int j=0;j<3;j++) printf("%c ",map[i][j]);printf("\n");}
}
};
class nodee
{
public:
int val,op;
nodee()
{
val=op=0;
}
}map[500000];
int check(node p)
{
int i,j,k;
int cout=0;
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
if(p.map[i][j]=='x') continue;
for(k=0;k<i*3+j;k++)
{
int ii=k/3,jj=k%3;
if(p.map[ii][jj]=='x') continue;
if(p.map[ii][jj]>p.map[i][j]) cout++;
}
}
}
return cout%2;
}
int geth(node p)
{
int i,j,k;
int cout=0;
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
if(p.map[i][j]=='x') continue;
k=p.map[i][j]-'1';
cout+=abs(k/3-i)+abs(k%3-j);
}
}
return cout;
}
int gethash(node p)
{
int i,j,k=0;
char a[9];
int sum=0;
for(i=0;i<3;i++)
for(j=0;j<3;j++) a[k++]=p.map[i][j];
for(i=0;i<9;i++)
{
k=0;
for(j=0;j<i;j++)
if(a[j]>a[i]) k++;
sum+=k*f[i];
}
return sum;
}
void print(node p)
{
int i;
i=p.hash;
string ans;
while(i!=-2)
{
//cout<<"i="<<i<<endl;
switch (map[i].op)
{
case 1:ans+='r';break;
case 2:ans+='l';break;
case 3:ans+='d';break;
case 4:ans+='u';break;
}
i=map[i].val;
// printf("i=%d map[i].val=%d\n",i,map[i].val);
if(i==-1) break;
}
long long ii;
for(ii=ans.size()-1;ii>=0;ii--) printf("%c",ans[ii]);printf("\n");
}
int judge(node p)
{
int i,j,k;
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
// printf("[%c %c] ",tar[i][j],p.map[i][j]);
/*if(p.map[i][j]=='x') continue;
k=p.map[i][j]-'0';
if(k!=i*3+j+1) return 0;*/
if(p.map[i][j]!=tar[i][j]) return 0;
}//printf("\n");
}
// cout<<"??!!!"<<endl;
return 1;
}
void solve(node init)
{
int i;
priority_queue<node>que;
init.g=0;
init.h=geth(init);
init.hash=gethash(init);
map[init.hash].val=-2;
que.push(init);
while(!que.empty())
{
node p=que.top(),tmp;
que.pop();
if(judge(p)) {//printf("map[311477]=%d map[311741]=%d\n",map[311477].val,map[311741].val);
print(p);//cout<<"??"<<endl;
return;}
for(i=0;i<4;i++)
{
tmp=p;
tmp.x+=cmp[i][0],tmp.y+=cmp[i][1];
if(tmp.x<0||tmp.x>2||tmp.y<0||tmp.y>2) continue;
tmp.map[p.x][p.y]=tmp.map[tmp.x][tmp.y];
tmp.map[tmp.x][tmp.y]='x';
tmp.hash=gethash(tmp);
if(map[tmp.hash].val!=-1||check(tmp)) continue;
map[tmp.hash].val=p.hash;
map[tmp.hash].op=i+1;
tmp.g++;tmp.h=geth(tmp);
que.push(tmp);
// printf("map[%d]=%d\n",tmp.hash,map[tmp.hash]);
// tmp.print();
}
}
}
void clear()
{
for(int i=0;i<500000;i++) map[i].val=map[i].op=-1;
}
int main()
{
char s[50];
while(gets(s))
{
clear();
char ss[10];
int i;
int top=0;
node init;
for(i=0;s[i]!='\0';i++) if(s[i]<='9'&&s[i]>='0'||s[i]=='x') ss[top++]=s[i];
// if(top==0) {printf("\n");break;}
for(i=0;i<top;i++)
{
init.map[i/3][i%3]=ss[i];
if(ss[i]=='x') init.x=i/3,init.y=i%3;
}
if(check(init)) {printf("unsolvable\n");continue;}
solve(init);
}
return 0;
}