双向广搜很早之前就像学习,但蒟蒻这道今天才会写(汗。。。)
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
八数码问题在oi界也算是妇孺皆知,有启发式搜索和DBFS两种解法,题目不在详细介绍,在这里给出我的解法
codevs 1225 八数码难题
比较原始的八数码,目标状态为123804765(即蛇形排列),双向广搜顾名思义,就是两头同时进行广搜,我们有了起点状态和目标状态,可以同时扩展,这道扩展出同一个叶子节点,注意hash判重,queue中的st为步数,col表示是从正序扩展而来还是从逆序扩展而来,exist存放编号,一旦出现hash值相同但col不同,就查询出来节点编号,把st相加即为结果。 code:
#include
#include
#include
using namespace std;
int fac[10]={1,1,2,6,24,120,720,5040,40320,362880};
int en[4][4]={0,0,0,0,0,1,2,3,0,8,0,4,0,7,6,5},st[4][4],head,tail;
int dx[5]={0,1,0,-1,0},dy[5]={0,0,1,0,-1};
int exist[500001][2];
struct hp{
int map[4][4],bx,by,col,st;
}queue[500001];
int hash(int i)
{
int j,k,m,p,sum=0,x;
for (j=1;j<=3;++j)
for (k=1;k<=3;++k)
{
x=0;
for (p=k+1;p<=3;++p)
x+=queue[i].map[j][k]>queue[i].map[j][p];
for (p=j+1;p<=3;++p)
for (m=1;m<=3;++m)
x+=queue[i].map[j][k]>queue[i].map[p][m];
sum+=x*fac[9-(j-1)*3-k];
}
return sum;
}
void init()
{
int i,j;
char c;
for (i=1;i<=3;++i)
for (j=1;j<=3;++j)
{
scanf("%c",&c);
st[i][j]=int(c)-48;
}
}
int bfs()
{
int bx1,by1,i,j,k,m,e,step,temp,std;
head=0; tail=2;
for (i=1;i<=3;++i)
for (j=1;j<=3;++j)
{
queue[2].map[i][j]=en[i][j];
queue[1].map[i][j]=st[i][j];
if (st[i][j]==0)
{
queue[1].bx=i;
queue[1].by=j;
}
if (en[i][j]==0)
{
queue[2].bx=i;
queue[2].by=j;
}
}
queue[1].col=0; queue[2].col=1;
queue[1].st=queue[2].st=0;
memset(exist,0,sizeof(exist));
exist[hash(1)][0]=1; exist[hash(2)][1]=2; step=0;
while (head=1&&bx1+dx[j]<=3&&by1+dy[j]>=1&&by1+dy[j]<=3)
{
tail++;
for (k=1;k<=3;++k)
for (m=1;m<=3;++m)
queue[tail].map[k][m]=queue[i].map[k][m];
queue[tail].bx=bx1+dx[j];
queue[tail].by=by1+dy[j];
queue[tail].map[bx1+dx[j]][by1+dy[j]]=0;
queue[tail].map[bx1][by1]=queue[i].map[bx1+dx[j]][by1+dy[j]];
queue[tail].col=queue[i].col;
queue[tail].st=step;
temp=hash(tail);
if (exist[temp][queue[tail].col])
tail--;
else
{
exist[temp][queue[tail].col]=tail;
if (exist[temp][1-queue[tail].col])
return step+queue[exist[temp][1-queue[tail].col]].st;
}
}
}
head=e;
}
return -1;
}
int main()
{
int num;
init();
num=bfs();
if (num!=-1)
printf("%d\n",num);
else
printf("unsolvable\n");
}
poj 1077 Eight 输出路径的八数码,稍麻烦 code:
#include
#include
#include
using namespace std;
int fac[10]={1,1,2,6,24,120,720,5040,40320,362880};
int en[4][4]={0,0,0,0,0,1,2,3,0,4,5,6,0,7,8,0},st[4][4],head,tail;
int dx[5]={0,1,0,-1,0},dy[5]={0,0,1,0,-1};
int exist[500001][2];
struct hp{
int map[4][4],bx,by,col,st,last;
char mov;
}queue[500001];
int hash(int i)
{
int j,k,m,p,sum=0,x;
for (j=1;j<=3;++j)
for (k=1;k<=3;++k)
{
x=0;
for (p=k+1;p<=3;++p)
x+=queue[i].map[j][k]>queue[i].map[j][p];
for (p=j+1;p<=3;++p)
for (m=1;m<=3;++m)
x+=queue[i].map[j][k]>queue[i].map[p][m];
sum+=x*fac[9-(j-1)*3-k];
}
return sum;
}
void init()
{
int i,j;
char c;
for (i=1;i<=3;++i)
for (j=1;j<=3;++j)
{
scanf("%c",&c);
if (c==' ')
scanf("%c",&c);
if (c!='x')
st[i][j]=int(c)-48;
else
st[i][j]=0;
}
}
void print1(int mid)
{
if (queue[mid].last!=1)
print1(queue[mid].last);
printf("%c",queue[mid].mov);
}
void print2(int mid)
{
printf("%c",queue[mid].mov);
if (queue[mid].last!=2)
print2(queue[mid].last);
}
int bfs()
{
int bx1,by1,i,j,k,m,e,step,temp,std;
head=0; tail=2;
for (i=1;i<=3;++i)
for (j=1;j<=3;++j)
{
queue[2].map[i][j]=en[i][j];
queue[1].map[i][j]=st[i][j];
if (st[i][j]==0)
{
queue[1].bx=i;
queue[1].by=j;
}
if (en[i][j]==0)
{
queue[2].bx=i;
queue[2].by=j;
}
}
queue[1].col=0; queue[2].col=1;
queue[1].st=queue[2].st=0;
memset(exist,0,sizeof(exist));
exist[hash(1)][0]=1; exist[hash(2)][1]=2; step=0;
while (head=1&&bx1+dx[j]<=3&&by1+dy[j]>=1&&by1+dy[j]<=3)
{
tail++;
for (k=1;k<=3;++k)
for (m=1;m<=3;++m)
queue[tail].map[k][m]=queue[i].map[k][m];
queue[tail].bx=bx1+dx[j];
queue[tail].by=by1+dy[j];
queue[tail].map[bx1+dx[j]][by1+dy[j]]=0;
queue[tail].map[bx1][by1]=queue[i].map[bx1+dx[j]][by1+dy[j]];
queue[tail].col=queue[i].col;
queue[tail].st=step;
queue[tail].last=i;
if (queue[tail].col==0)
{
if (j==1) queue[tail].mov='d';
if (j==2) queue[tail].mov='r';
if (j==3) queue[tail].mov='u';
if (j==4) queue[tail].mov='l';
}
if (queue[tail].col==1)
{
if (j==1) queue[tail].mov='u';
if (j==2) queue[tail].mov='l';
if (j==3) queue[tail].mov='d';
if (j==4) queue[tail].mov='r';
}
temp=hash(tail);
if (exist[temp][queue[tail].col])
tail--;
else
{
exist[temp][queue[tail].col]=tail;
if (exist[temp][1-queue[tail].col])
{
if (queue[tail].col==0)
{
print1(tail);
print2(exist[temp][1-queue[tail].col]);
}
else
{
print1(exist[temp][1-queue[tail].col]);
print2(tail);
}
return step+queue[exist[temp][1-queue[tail].col]].st;
}
}
}
}
head=e;
}
return -1;
}
int main()
{
int num;
init();
num=bfs();
if (num==-1)
printf("unsolvable\n");
}