[啟發式搜索/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;
}

而對於上題的搜索則需要最優性剪枝,通過變化數組的遍歷方式防止走回去


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM