poj 1077八数码
诶嘛,做出来了老开心了
据说是此生一定要做的搜索,为了干掉他补了一周的知识,大概有启发式搜索啊,A*算法啊,还有优先队列,自定义优先级,重载比较符号,C++堆的用法等等,现在只写出来了bfs+contort,可能以后会再发一篇A*的把、、、
大概想法是用康托编号代替排列方法作为下表存储父节点啊,路径啊,是否访问啊etc。发现有了康托以后真的很方便呢(笑)。从结尾,即末尾状态开始建树,直到搜到了与给定康托编码一样的棋盘,注释写的应该还蛮仔细的(不写仔细点我自己也看不懂XD)。
数据存储结构真的重写了好多遍好多遍,,每次发现更优储存方法的时候都好崩溃TAT;
比较坑的地方是因为是逆向搜索,最后输出的方向要反过来!!要反过来!!要反过来!!
然后我们上代码把!
#include<iostream>
#include<queue>
#include<stdio.h>
#define len 370000
using namespace std;
int fac[10];
char path[len];
int fath[len];
bool flag=false;
void facc() //阶乘
{
fac[0]=1;
int k=1;
for(int i=1; i<=9; i++)
{
k*=i;
fac[i]=k;
}
}
int dire[4]= {1,-1,-3,+3}; //上下左右
bool visted[len]= {false}; //以康托编码为下标的是否访问
struct chess
{
int con;
char cb[10];//棋盘状态cb[0]无意义
int ops;
} ;
int contor(char aa[]) //康托转码
{
int ans=0;
char x;
int counte=0;
for(int i=1; i<=9; i++)
{
x=aa[i];
counte=0;
for(int j=i+1; j<=9; j++)
{
if(x>aa[j])counte++;
}
ans+=fac[9-i]*counte;
}
return ans;
}
void bfs(int conto)
{
queue<chess> qq;
chess goal;
for(int i=1; i<=9; i++)
{
goal.cb[i]=i+'0';
}
goal.con=contor(goal.cb);
path[goal.con]='0';
fath[goal.con]=-1;
goal.ops=9;
visted[goal.con]=true;
qq.push(goal);
chess cur;
int x,xx;
while(!qq.empty())
{
cur=qq.front();
qq.pop();
x= cur.ops;
for(int i=0; i<4; i++)
{
if(x%3==1)//不能左转
{
if(i==1)
{
continue;
}
}
if(x%3==0)//不能右转
{
if(i==0)
{
continue;
}
}
if(x>=1&&x<=3)//不能向上
{
if(i==2)continue;
}
if(x>=7&&x<=9)//不能向下
{
if(i==3)continue;
}
xx=x+dire[i];
if(xx>=1&&xx<=9)
{
chess c=cur;
c.cb[x]=cur.cb[xx];
c.cb[xx]=9+'0';
int con2=contor(c.cb);
if(!visted[con2])
{
c.ops=xx;
fath[con2]=cur.con;
c.con=con2;
visted[con2]=true;
switch(i)
{
case 0:
path[con2]='l';
break;
case 1:
path[con2]='r';
break;
case 2:
path[con2]='d';
break;
case 3:
path[con2]='u';
break;
}
if(con2==conto){
flag=true;
int w;
w=con2;
while(w!=goal.con){
printf("%c",path[w]);
w=fath[w];
}
printf("\n");
}
qq.push(c);
}
}
}
}
if(flag==true)return;
if(flag==false){
printf("unsolvable\n");
return;
}
}
int main()
{
facc();
//写一个终末状态节点,然后向前搜
char a[10];
char p;
bool f=true;
int i=1;
while(f){
scanf("%c",&p);
if(p==' ')continue;
else if(p=='x'){
a[i]=9+'0';
i++;
}else {
a[i]=p;i++;}
if(i==10){
break;
}
}
// for(int i=1;i<=9;i++){
// printf("%c",a[i]);
//}
int con=contor(a);
bfs(con);
return 0;
}