您的位置:首页 > 其它

HDU 1043 八数码 反向BFS+康拓展开

2017-07-16 22:13 351 查看

题意

八数码,末状态”12345678x”

题解

POJ八数码用普通BFS+康拓展开过了。但是HDU1043却过不了,看了题解才知道要反向BFS打表。有关康拓展开,可以参考相关百度文库文档。反向BFS的思路就是从末状态开始BFS搜索到达所有状态的路径,八数码问题总共也就三十多万个状态,每个状态路径可以用string进行存储,并使用康拓展开进行编码。针对每一组数据,进行编码后直接到string数组中查找即可。

代码

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<string>
#include<strstream>
#define INF 1e9

using namespace std;
typedef int State[9];

State tar={1,2,3,4,5,6,7,8,9};
const int maxState=400000;
bool vis[maxState];
string path[maxState];
int fact[10];
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};

void init(){
memset(vis,false,sizeof(vis));
fact[0]=1;
for(int i=1;i<9;i++){
fact[i]=fact[i-1]*i;
}
}
string addDir(int i){
if(i==0)
return "l";
if(i==1)
return "r";
if(i==2)
return "u";
if(i==3)
return "d";
}

int calCode(State news){
int code=0;
for(int i=0;i<9;i++){
int cnt=0;
for(int j=i+1;j<9;j++){
if(news[j]<news[i]){
cnt++;
}
}
code+=fact[8-i]*cnt;
}
return code;
}

int bfs(){
init();
queue<int> que;
que.push(123456789);
while(!que.empty()){
int ft=que.front();
que.pop();
State s;
for(int i=8;i>=0;i--){
s[i]=ft%10;
ft/=10;
}
int z=-1;
for(int i=0;i<9;i++){
if(s[i]==9){
z=i;
break;
}
}
int x=z/3,y=z%3;
for(int i=0;i<4;i++){
State news;

int newx=x+dir[i][0];
int newy=y+dir[i][1];
int newz=newx*3+newy;
if(newx<0||newy<0||newx>=3||newy>=3)
continue;
memcpy(&news,&s,sizeof(s));
news[newz]=s[z];
news[z]=s[newz];
int code=calCode(news);
if(vis[code])
continue;
else{
vis[code]=true;
path[code]=path[calCode(s)]+addDir(i);
int sum=0;
for(int i=0;i<9;i++){
sum=sum*10+news[i];
}
que.push(sum);
}
}
}
return 0;
}

int main()
{
bfs();
char s[100];
for(int i=0;i<400000;i++){
reverse(path[i].begin(),path[i].end());
}
while(cin.getline(s,50)){
State st;
int pos=0;
for(int i=0;i<strlen(s);i++){
if(pos==9)
break;
if(s[i]==' ')
continue;
if(s[i]=='x')
st[pos++]=9;
else
st[pos++]=s[i]-'0';
}

int rev1=0;
for(int i=0;i<9;i++){
if(st[i]==9)
continue;
for(int j=0;j<i;j++){
if(st[j]==9)
continue;
if(st[j]>st[i]){
rev1++;
}
}
}
if(rev1%2!=0)
cout<<"unsolvable"<<endl;
else{
cout<<path[calCode(st)]<<endl;
}

}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: