洛谷 P2324 [SCOI2005]骑士精神

来源:互联网 发布:windows程序设计算c 编辑:程序博客网 时间:2024/05/21 07:16

传送门

开始怼网络流24题所以发的比较晚,学习一下A*搜索,A*其实就是加入评估函数对有限步数或能估价有效的剪枝,对于A*一般只有dfs(bfs被成为最愚蠢的A*)。

这题的估价函数:当前棋盘与目标棋盘不同的位置数量-1(评估函数是当前状态到目标状态的距离),所以就有:

当前不相同的骑士个数 + 当前步数 <= 期望最大步数

若不满足就剪枝

代码:

#include<iostream>#include<stdio.h>using namespace std;char graph[7][7]={    "000000",      "011111",      "001111",      "000*11",      "000001",      "000000"};char c[7][7];int now,flag;inline int ftry(){    int ans=0;    for(int i=1;i<=5;i++)        for(int j=1;j<=5;j++)            ans+=(c[i][j]!=graph[i][j]);    return ans-1;}inline void dfs(int depth,int x,int y){    int p=ftry();    if(p==-1)    {        flag=1;        return ;    }    if(p+depth>now)return ;        if(x+2<=5&&y+1<=5&&x+2>=1&&y+1>=1){swap(c[x+2][y+1],c[x][y]);dfs(depth+1,x+2,y+1);swap(c[x+2][y+1],c[x][y]);if(flag)return ;}            if(x+2<=5&&y-1>=1&&x+2>=1&&y-1<=5){swap(c[x+2][y-1],c[x][y]);dfs(depth+1,x+2,y-1);swap(c[x+2][y-1],c[x][y]);if(flag)return ;}            if(x-2>=1&&y+1<=5&&x-2<=5&&y+1>=1){swap(c[x-2][y+1],c[x][y]);dfs(depth+1,x-2,y+1);swap(c[x-2][y+1],c[x][y]);if(flag)return ;}            if(x-2>=1&&y-1<=5&&x-2<=5&&y-1>=1){swap(c[x-2][y-1],c[x][y]);dfs(depth+1,x-2,y-1);swap(c[x-2][y-1],c[x][y]);if(flag)return ;}            if(x+1<=5&&y+2<=5&&x+1>=1&&y+2>=1){swap(c[x+1][y+2],c[x][y]);dfs(depth+1,x+1,y+2);swap(c[x+1][y+2],c[x][y]);if(flag)return ;}            if(x+1<=5&&y-2>=1&&x+1>=1&&y-2<=5){swap(c[x+1][y-2],c[x][y]);dfs(depth+1,x+1,y-2);swap(c[x+1][y-2],c[x][y]);if(flag)return ;}            if(x-1>=1&&y+2<=5&&x-1<=5&&y+2>=1){swap(c[x-1][y+2],c[x][y]);dfs(depth+1,x-1,y+2);swap(c[x-1][y+2],c[x][y]);if(flag)return ;}            if(x-1>=1&&y-2>=1&&x-1<=5&&y-2<=5){swap(c[x-1][y-2],c[x][y]);dfs(depth+1,x-1,y-2);swap(c[x-1][y-2],c[x][y]);if(flag)return ;}    }int main(){    int t;    scanf("%d",&t);    while(t--)    {        int x,y;        flag=0;        for(int i=1;i<=5;i++)        {            scanf("\n");            for(int j=1;j<=5;j++)            {                scanf("%c",&c[i][j]);                if(c[i][j]=='*')                    x=i,y=j;                                }        }        for(now=0;now<=15;now++)        {            dfs(0,x,y);            if(flag)                break;        }        if(now==16)            now=-1;        printf("%d\n",now);    }    return 0;}