八码数-IDA*算法

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;
}

你可能感兴趣的:(搜索)