A是用在BFS上的 A=优先队列+估价函数
IDA是用在DFS上的 IDA=迭代加深+估价函数
一般来说IDA优于A主要在A的BSF内存的需求,且不需要对启发值排序。我是更喜欢用IDA*。
IDA*相对于DFS有两个特点:运用了迭代加深的思路和乐观函数。
具体原理我怕讲不清楚,推荐阅读:
算法思想:迭代加深
A ∗ * ∗算法 和 IDA ∗ * ∗算法
看题吧:
HDU1043—Eight
给出一个 3 × 3 3×3 3×3的八码数0-8,0可以和它上下左右的数字交换,最后把题目给出的八码数变成1 2 3 / 4 5 6 / 7 8 0。给出最优解的方案(操作数最少)。
乐观函数设置为每个数到目标位置的曼哈顿距离,0除外。因为乐观的设想是最少每一步都在把数字往目标处移动。虽然基于曼哈顿距离,但假设的是最少移动步数,例如最后一步8在0的目标位置,0在8的目标位置曼哈顿和为2,但其实只需要一步。另外可以做一个小优化:下一个方向和当前的方向不能相反(这个优化很有效)。
关于八数码有无解的判定可以看这个: 八数码问题有解的条件及其推广
//#include
#include
#include
#include
#include
#include
using namespace std;
int stand[20][2]={ {3,3},{1,1},{1,2},{1,3},{2,1},{2,2},{2,3},{3,1},{3,2}};
int C[5][5];
int dx[] = {1,0,0,-1};
int dy[] = {0,-1,1,0};
char dir[] = {'d','l','r','u'};
char c[20];
int Success;
char process[500];
int Check(){
int cnt=0;
for(int i=1;i<=3;++i){
for(int j=1;j<=3;++j){
if(C[i][j]==0) continue;
int dx=abs(stand[C[i][j]][0]-i);
int dy=abs(stand[C[i][j]][1]-j);
cnt+=dx+dy;
}
}
return cnt;
}
void dfs(int ox,int oy,int pre,int dep,int maxdep){
int Che=Check();
if(Che==0) {
Success=dep;
printf("%s\n",process);
return ;
}
if(Che+dep>maxdep){
return ;
}
for(int i=0;i<=3&&Success==-1;++i){
if(pre+i==3) continue;
int nx=ox+dx[i],ny=oy+dy[i];
if(nx<=0||nx>3||ny<=0||ny>3) continue;
swap(C[ox][oy],C[nx][ny]);
process[dep]=dir[i];
dfs(nx,ny,i,dep+1,maxdep);
swap(C[ox][oy],C[nx][ny]);
}
}
bool judge(){
int cnt=0;
for(int i=1;i<=9;++i){
if(c[i]=='x') continue;
for(int j=i+1;j<=9;++j){
if(c[j]=='x') continue;
if(c[j]>c[i]) ++cnt;
}
}
return cnt%2==0;
}
int main(){
while(~scanf(" %c",&c[1])){
memset(process ,0,sizeof process);
for(int i=2;i<=9;++i){
scanf(" %c",&c[i]);
}
int ox,oy;
for(int i=1;i<=3;++i){
for(int j=1;j<=3;++j){
if(c[(i-1)*3+j]=='x') {
ox=i,oy=j;
C[i][j]=0;
}
else
C[i][j]=c[(i-1)*3+j]-'0';
}
}
if(!judge()) {
printf("unsolvable\n");
continue;
}
if(Check()==0) {
printf("\n");
continue;
}
Success=-1;
for(int i=1;i<=1000000;++i){
dfs(ox,oy,-1,0,i);
if(Success!=-1) break;
}
}
return 0;
}
LG 骑士精神
#include
using namespace std;
char a[6][6];
int A[6][6];
int Move[9][2]={{0,0},{1,2},{2,1},{-1,2},{-2,1},{2,-1},{1,-2},{-2,-1},{-1,-2},
};
int Stand[6][6]={{0,0,0,0,0,0},{0,1,1,1,1,1} ,{0,0,1,1,1,1} ,{0,0,0,2,1,1},
{0,0,0,0,0,1},{0,0,0,0,0,0}};
int check(){
int cnt=0;
for(int i=1;i<=5;++i){
for(int j=1;j<=5;++j){
if(Stand[i][j]!=A[i][j]&&A[i][j]!=2) ++cnt;
}
}
return cnt;
}
int succe=-1;
void dfs(int xo,int yo,int pre,int dep,int maxdep){
int Check=check();
if(Check==0) {
succe=dep;
return ;
}
if(Check+dep>maxdep) {
return ;
}
for(int i=1;i<=8&&succe==-1;++i){
if(pre+i==9) continue;
int tx=xo,ty=yo;
int nx=xo+Move[i][0],ny=yo+Move[i][1];
if(!(nx<=0||nx>5||ny<=0||ny>5)){
int t=A[nx][ny];
A[xo][yo]=t;
A[nx][ny]=2;
dfs(nx,ny,i,dep+1,maxdep);
A[nx][ny]=t;
A[xo][yo]=2;
}
}
}
int main(){
int t;
scanf("%d",&t);
while(t--){
int xo,yo;
for(int i=1;i<=5;++i){
scanf("%s",a[i]+1);
for(int j=1;j<=5;++j){
if(a[i][j]=='*'){
xo=i,yo=j;
A[i][j]=2;
}
else A[i][j]=a[i][j]-'0';
}
}
succe=-1;
if(check()==0) printf("0\n");
else {
for(int i=2;i<=15;++i){
dfs(xo,yo,-1,0,i);
if(succe!=-1){
break;
}
}
printf("%d\n",succe);
}
}
return 0;
}