[启发式搜索/A*] [SCOI2005]骑士精神题解

洛谷-骑士精神

启发式搜索-A*

估价函数

对于当前状态,我们可以将其与目标状态对比,得到一个预估的代价,即最少(不一定满足题意)的代价,得到这个代价的函数叫做估价函数

对于一个最短路问题来说,我们可以定义一个如下的函数式来表示搜索的过程

\[f^*(x)=g^*(x)+h^*(x) \]

其中,f*(x)为从x到目标节点预估的总代价,g*(x)表示目前到达x点已经付出的代价,h*(x)表示预估从x到目标的最小代价,如上题(骑士精神)中,f(x)用迭代加深枚举出来,g(x)为已经走的步数(已知),h*(x)则可表示为目前局面与目标局面的不同点的个数。

上题代码

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int a[5][5];
int _std[5][5]= {
    {1,1,1,1,1},
    {0,1,1,1,1},
    {0,0,-1,1,1},
    {0,0,0,0,1},
    {0,0,0,0,0}
};
int dx[]={0,-2,-2,-1,-1,1,1,2,2};    //重点,剪枝,两边对称并在下面判断防止走回去
int dy[]={0,-1,1,-2,2,-2,2,-1,1};
int ans;
int lim;
int fc()
{
    int ret=0;
    for(int i=0; i<5; i++) {
        for(int j=0; j<5; j++) {
            if(a[i][j]!=_std[i][j]) {
                ret++;
            }
        }
    }
    return ret;
}
void dfs(int x,int y,int step,int f)
{
    int diff=fc();
    if(diff+step>lim)return;
    if(step>=ans)return;
    if(diff==0) {
        ans=step;
        return;
    }
    for(int i=1; i<=8; i++) {
        if(x+dx[i]<0||(x+dx[i]>4)) continue;
        if(y+dy[i]<0||(y+dy[i]>4)) continue;
        if(i+f!=9) {
            swap(a[x+dx[i]][y+dy[i]],a[x][y]);
            dfs(x+dx[i],y+dy[i],step+1,i);
            swap(a[x+dx[i]][y+dy[i]],a[x][y]);
        }
    }
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--) {
        int x,y;
        ans=20;
        int dif=0;
        for(int i=0; i<5; i++) {
            for(int j=0; j<5; j++) {
                char tmp;
                cin>>tmp;
                if(tmp=='1') {
                    a[i][j]=1;
                }
                if(tmp=='0') {
                    a[i][j]=0;
                }
                if(tmp=='*') {
                    a[i][j]=-1;
                    x=i;
                    y=j;
                }
                if(a[i][j]!=_std[i][j])dif++;
            }
        }
        for(int i=dif;i<=16;i++){
            lim=i;
            dfs(x,y,0,0);
        }
        printf("%d\n",ans==20? -1:ans);
    }
    return 0;
}

而对于上题的搜索则需要最优性剪枝,通过变化数组的遍历方式防止走回去

posted @ 2018-10-22 20:33  smallshulker  阅读(941)  评论(4编辑  收藏  举报