BZOJ1085: [SCOI2005]骑士精神(IDA*搜索)

题意:传送门

题解:要了解IDA*,首先需要了解迭代加深,

定义:每次限定一个maxdepmaxdep最大深度,使搜索树的深度不超过maxdepmaxdep。

使用范围:需要在有一定限制条件下使用

优点:可能会在一个没有解,或者很深的地方无限递归而题目种没有要求输出任何的一组解,所以限制一个深度,让它遍历更多的分治,去更广泛地求解。

其次需要了解估价函数

定义:f(n)=g(n)+h(n),其中f(n)是节点的估价函数,g(n)是现在的实际步数,h(n)是对未来步数的最完美估价。

最后A*是用于对BFS的优化,IDA*是对迭代加深的DFS的优化,本质上都是对BFS和DFS加上一个估价函数。

最后最重要的就是对估价函数的推导,推到的不好也就是h(n)=0,仍然相当于暴搜,推导的不好还可能WA。

附上代码:

#include<bits/stdc++.h>
using namespace std;
int ans[5][5]={{1,1,1,1,1},{0,1,1,1,1},{0,0,2,1,1},{0,0,0,0,1},{0,0,0,0,0}};
int xx[]={1,1,-1,-1,2,2,-2,-2};
int yy[]={2,-2,2,-2,1,-1,1,-1};
int T,k,a[5][5],flag;
char ch[10];
bool judge()
{
    for(int i=0;i<5;i++){
        for(int j=0;j<5;j++){
            if(a[i][j]!=ans[i][j])return 0;
        }
    }
    return 1;
}
bool eva(int s)
{
    int v=0;
    for(int i=0;i<5;i++){
        for(int j=0;j<5;j++){
            if(a[i][j]!=ans[i][j])v++;
        }
    }
    if(s+v>k)return false;
    else return true;
}
void search(int s,int x,int y)
{
    if(s>k)return ;
    if(s==k){if(judge())flag=1;return ;}
    if(flag)return ;
    for(int i=0;i<8;i++){
        int nx=x+xx[i],ny=y+yy[i];
        if(nx<0||nx>4||ny<0||ny>4)continue;
        swap(a[x][y],a[nx][ny]);
        if(eva(s))search(s+1,nx,ny);
        swap(a[x][y],a[nx][ny]);
    }
}
int main()
{
    scanf("%d",&T);
    while(T--){
        int x,y;
        for(int i=0;i<5;i++){
            scanf("%s",ch);
            for(int j=0;j<5;j++){
                if(ch[j]!='*')a[i][j]=ch[j]-'0';
                else x=i,y=j,a[i][j]=2;
            }
        }

        for(k=1;k<=15;k++){
            search(0,x,y);
            if(flag){
                printf("%d\n",k);
                break;
            }
        }
        if(!flag)printf("-1\n");
        flag=0;
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值