您的位置:首页 > 其它

洛谷 P1379 八数码难题

2017-08-10 13:33 253 查看
啊!!这一题算是BFS中的经典了,如果你不懂BFS的话,可以睡觉了~~~

现在请大家跳转题面

题目描述

在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。

输入输出格式

输入格式:
输入初试状态,一行九个数字,空格用0表示

输出格式:
只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)

输入输出样例

输入样例#1:
283104765
输出样例#1:
4


啊!!现在我们来分析一下思路

1.使用3*3的数组存储,操作十分简单,但会超时很多点,有兴趣的读者可以自行尝试一下;

2.程序中用3*3的二维数组表示布局比较直观,但在判断重复,判断是否达到目标方面,却给程序增加了复杂性,也影响了运行速度。可以改用字符串形式来表示布局,第1..3个数表示第一行的三个数,第4..6个数,表示第二行的三个数,第7..9个数表示第三行的三个数。这样,程序的判断和判重可以方便很多。

但如判重时使用的是一个存下所有情况的数组,那也能拿10分。

如:10分代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
int hash1=1,f[51000];
string go,to,hashb[51000],ans[51000];
int h=0,t=1;
int a[4]={1,-1,0,0},
b[4]={0,0,1,-1};
int out(int t)
{  int s=0;
do{s++;
t=f[t];
}while(f[t]!=0);
return s;
}
int pz(int n)
{
for(int i=1;i<=n;i++)
if(hashb[i]==ans[h]) return 0;
return 1;
}
int bfs()
{
ans[1]=go;f[1]=0;
do{int i;

h++;
for( i=0;i<=8;i++)
if(ans[h][i]=='0') break;
for(int x=0;x<4;x++)
{
int nowx,nowy,tox,toy,wz;
nowx=i/3+1;
nowy=i%3+1;
tox=nowx+a[x];
toy=nowy+b[x];
wz=(tox-1)*3+toy-1;
if(tox>=1&&tox<=3&&toy>=1&&toy<=3&&wz>=0&&wz<=8&&nowx>=1&&nowx<=3&&nowy>=1&&nowy<=3)
{
char c;
c=ans[h][wz];
ans[h][wz]=ans[h][i];
ans[h][i]=c;

if(pz(hash1)==1) {
t++;ans[t]=ans[h];
f[t]=h;
hashb[++hash1]=ans[t];
if(ans[t]==to) {return out(t);}

}
c=ans[h][i];
ans[h][i]=ans[h][wz];
ans[h][wz]=c;

}
}

}while(h<t);
}
int main()
{
cin>>go;
hashb[1]=go;
to="123804765";
int answer;
answer=bfs();
printf("%d",answer);

return 0;
}


现在我们发现判重的时候浪费了许多时间,所以我们可使用MAP或康托展开

100分(MAP)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<string>
#include<map>
using namespace std;
int hash1=1,f[510000];
string go,to,ans[510000];
int h=0,t=1;
int a[4]={1,-1,0,0},
b[4]={0,0,1,-1};
map<string,int>hashb;
int out(int t)
{  int s=0;
do{s++;
t=f[t];
}while(f[t]!=0);
return s;
}
int bfs()
{
ans[1]=go;f[1]=0;
do{int i;

h++;
for( i=0;i<=8;i++)
if(ans[h][i]=='0') break;
for(int x=0;x<4;x++)
{
int nowx,nowy,tox,toy,wz;
nowx=i/3+1;
nowy=i%3+1;
tox=nowx+a[x];
toy=nowy+b[x];
wz=(tox-1)*3+toy-1;
if(tox>=1&&tox<=3&&toy>=1&&toy<=3&&wz>=0&&wz<=8&&nowx>=1&&nowx<=3&&nowy>=1&&nowy<=3)
{
char c;
c=ans[h][wz];
ans[h][wz]=ans[h][i];
ans[h][i]=c;

if(hashb[ans[h]]!=1) {
t++;ans[t]=ans[h];
f[t]=h;
hashb[ans[h]]=1;
if(ans[t]==to) {return out(t);}

}
c=ans[h][i];
ans[h][i]=ans[h][wz];
ans[h][wz]=c;

}
}

}while(h<t);
}
int main()
{
cin>>go;
hashb[go]=1;
to="123804765";
int answer;
answer=bfs();
printf("%d",answer);

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