BZOJ 1085 浅谈迭代加深式法则及Astar启发式搜索路径诱导

来源:互联网 发布:淘宝清除缓存 编辑:程序博客网 时间:2024/06/05 00:28

这里写图片描述
世界真的很大
Astar的第二题,在Astar剪枝的同时使用了迭代加深的搜索方式
将谈谈迭代加深搜索和Astar的估价函数在剪枝方面的应用
听起来可能感觉不可做其实就是暴力+优化而已
搜索题写起来还是很舒服的只是调起来就不是那么亲民了
好在调的还算比较快

看题先:

description:

 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位。在任何时候一个骑士都能按照骑
士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵坐标相差为1的格子)移动到空
位上。 给定一个初始的棋盘,怎样才能经过移动变成如下目标棋盘: 为了体现出骑士精神,他们必须以最少的步
数完成任务。
这里写图片描述

input:

第一行有一个正整数T(T<=10),表示一共有N组数据。接下来有T个5×5的矩阵,0表示白色骑士,1表示黑色骑
士,*表示空位。两组数据之间没有空行。

output:

对于每组数据都输出一行。如果能在15步以内(包括15步)到达目标状态,则输出步数,否则输出-1。

考虑直接爆搜
但是爆搜有一个问题,就是考虑在搜索树上,如果当前搜索路径上没有答案,那么其实这条搜索路径就是不必要的
但是我们事先并不知道有没有答案,DFS是不撞南墙不回头的
所以会直线搜索下去,很可能会爆栈然后卡死
迭代加深搜索适用的,就是这种情况
我们人为地限制搜索树的高度,然后枚举这个高度多次搜索
在搜索树扩散很快,转移很多的时候这种方法尤其好用

即我们从小到大枚举步数,然后搜索在这个步数内能不能搜索到答案
这算是一般搜索的一个优化吧

然后这样可能时间上还是有一点卡或者说还是会超时
需要进一步优化搜索
Astar算法,就是搜索的一个强有力的剪枝,剪枝力度及正确性取决与估价函数的精度的一个算法

如果要用Astar来剪枝的话,估价函数,即 f = g + h 里面的h怎么办呢
h的含义就是指我估计从当前局面到目标局面所走的步数
那么g就是指我已经走的步数
如何估计我还要走多少步呢?
这个的确是比较难以处理,具体值实在是难以把握,但如果因为估计的失误导致搜索漏掉正解的话,就得不偿失了
所以我们宁可估价函数的力度小一点,也不要让他出错
那就估计一个相对准确的“下界”,如何?
即至少要走多少步

这个我们就通过当前局面和目标局面有多少个不同之处来判断了
因为如过当前局面与目标局面有x个位置不同,至少再走x-1步对吧
这是由于空的位置只有
用这个来充当估价函数来估计准确的下界就没问题了
如果加上这个这个函数之后大于了迭代值就不继续搜索了

完整代码:

#include<stdio.h>#include<algorithm>#include<cstring>using namespace std;int T;int mp[6][6],sd[6][6];int fx[8]={1,1,2,2,-1,-1,-2,-2},fy[8]={-2,2,-1,1,-2,2,-1,1};char ss[10];void init(){    for(int i=1;i<=5;i++)        for(int j=1;j<=5;j++)            if(j>=i && i<=2) sd[i][j]=1;            else if(j>i && i>=3) sd[i][j]=1;            else if(i==3&&j==3) sd[i][j]=2;}bool check(){    for(int i=1;i<=5;i++)        for(int j=1;j<=5;j++)            if(mp[i][j]!=sd[i][j]) return false ;    return true ;}int estimate(){    int rt=0;    for(int i=1;i<=5;i++)        for(int j=1;j<=5;j++)            rt+=(mp[i][j]!=sd[i][j]);    return rt-1;}bool dfs(int x0,int y0,int maxn,int state){    if(state==maxn) return check();    for(int i=0;i<8;i++)    {        int x1=x0+fx[i],y1=y0+fy[i];        if(x1<1 || x1>5 || y1<1 || y1>5) continue ;        swap(mp[x0][y0],mp[x1][y1]);        if(estimate()+state<=maxn)             if(dfs(x1,y1,maxn,state+1)) return 1;        swap(mp[x0][y0],mp[x1][y1]);    }    return 0;}int main(){    init();    scanf("%d",&T);    while(T--)    {        int flag=1,Sx,Sy;        for(int i=1;i<=5;i++)        {            scanf("%s",ss+1);            for(int j=1;j<=5;j++)                if(ss[j]=='1') mp[i][j]=1;                else if(ss[j]=='0') mp[i][j]=0;                else mp[i][j]=2,Sx=i,Sy=j;        }               for(int i=0;i<=15;i++)            if(flag && dfs(Sx,Sy,i,0))                flag=0,printf("%d\n",i);                if(flag) printf("-1\n");    }    return 0;}/*Whoso pulleth out this sword from this stone and anvil is duly born King of all England*/

嗯,就是这样

阅读全文
0 0