zoukankan      html  css  js  c++  java
  • P2324 [SCOI2005]骑士精神(A*)

    P2324 [SCOI2005]骑士精神

    A*与爆搜的不同就是它有一个估价函数$h(x)$

    这个估价函数一般设为从当前状态到终点状态的估计最短步数,这样可以有效剪枝

    但估计值必须严格小于等于实际剩余步数,否则会剪枝过度而影响正确性

    $g(x),f(x)$分别为剩余步数和已走步数,则:

    $g(x)=f(x)+h(x)$

    本题中的$h(x)$可以设为未归位的棋子数+1

    因为每一步最多使一个棋子归位(除最后一步一次归位2个棋子)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    
    int d1[8]={1,1,2,2,-1,-1,-2,-2};
    int d2[8]={2,-2,1,-1,2,-2,1,-1};
    char a[9][9]; int re,col[9][9];
    inline bool is(int x,int y){return (x==3&&y==3)?(a[x][y]=='*'):(a[x][y]==col[x][y]+'0');}
    void dfs(int d,int s,int x,int y){//d当前步数,s已归位棋子个数
        if(d+24-s>=re||d>15) return ;//f(x)=d,g(x)=24-s
        if(s==25) {re=min(re,d); return ;}
        for(int i=0;i<8;++i){
            int rx=x+d1[i],ry=y+d2[i],p=s;
            if(rx<1||5<rx||ry<1||5<ry) continue;
            p-=is(x,y)+is(rx,ry);
            swap(a[x][y],a[rx][ry]);
            p+=is(x,y)+is(rx,ry);
            dfs(d+1,p,rx,ry);
            swap(a[x][y],a[rx][ry]);
        }
    }
    int main(){
        for(int i=1;i<=5;++i) for(int j=i;j<=5;++j) col[i][j]=1;
        col[4][4]=col[5][5]=0;
        int T,sum,fx,fy;scanf("%d",&T);
        while(T--){
            sum=0; re=16;
            for(int i=1;i<=5;++i){
                scanf("%s",a[i]+1);
                for(int j=1;j<=5;++j){
                    sum+=is(i,j);
                    if(a[i][j]=='*') fx=i,fy=j;
                }
            }dfs(0,sum,fx,fy);
            if(re>15) re=-1;
            printf("%d
    ",re);
        }return 0;
    } 
  • 相关阅读:
    站立会议01---个人总结
    团队项目的NABCD
    查找水王
    《构建之法》读书笔记03
    《构建之法》读书笔记02
    《构建之法》读书笔记01
    Java web应用开发技术
    Java 模拟ATM(修正)
    Java 多态
    Java 接口与继承 道至简第六章发表阅读笔记
  • 原文地址:https://www.cnblogs.com/kafuuchino/p/11285586.html
Copyright © 2011-2022 走看看