• CDOJ1669 棋盘游戏 [A*]


      这题要用到A*。每个状态N记录个f(N)值,等于从初始状态走到该状态的实际花费g(N)+从该状态到目标状态花费的估计值h(N)。h(N)要小于等于从该状态到目标状态的实际花费。h(N):棋盘上剩余点到出口的曼哈顿距离之和。
      在BFS时,优先考虑f(N)值小的,在f(N)相同时,考虑当前花费g(N)小的。为了每次找到f(N)最小的点,可以用堆(STL中的优先队列)来保存状态。
      状态表示:最多四个棋子,坐标最大是n(n<=6),所以可以用一个整数来表示,相当于n进制数。
      BFS时的状态扩展就很简单了,每个棋子都可向四个方向走一步,判断走的位子是否在棋盘内,是否是空的,是否和其他棋子相邻。每次走后最小的棋后判断是否在出口,是的话就拿掉了。

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<string>
    #include<cmath>
    #include<iostream>
    #include<algorithm>
    #include<deque>
    #include<queue>
    #include<vector>
    using namespace std;
    
    typedef struct{
        int f,num,t;
        int loc[4];
    }node;
    
    int check[2000000],n,m,a[8][8],exitloc,mod;
    
    struct cmp{
        bool operator()(const node& a,const node& b){
            if(a.f>b.f) return true;
            if(a.f==b.f && check[a.num]>check[b.num]) return true;
            return false;
        }
    };
    priority_queue<node,vector<node>,cmp> Q;
    
    int trans(node nd,int m){
        int num=0,i;
        for(i=0; i<m; i++){
            num*=mod;
            num+=nd.loc[i];
        }
        return num;
    }
    
    void ini(int n,int m){
        int k=1,i,j;
        for(i=0; i<m; i++) k*=mod;
        for(i=0; i<=k; i++) check[i]=0;
        for(i=0; i<n; i++)
            for(j=0; j<n; j++)
                a[i][j]=0;
    }
    
    int H(node nd){
        int i,num=0,k;
        for(i=0; i<m; i++) {
            k=nd.loc[i];
            if(k!=0)
                num+=abs((k-1)/n - (exitloc-1)/n) + abs((k-1)%n - (exitloc-1)%n);
        }
        return num;
    }
    
    void BFS(){
        int k,i,j,xx,yy,x,y,min,num2,t;
        node nd,nd2;
        while(!Q.empty()){
            nd=Q.top();
            Q.pop();
            if(check[0]>0)return;
            min=m;
            for(i=0; i<m; i++){
                k=nd.loc[i];
                if(k==0) continue;
                a[(k-1)/n][((k-1)%n)]=i+1;
                if(i+1<min) min=i+1;
            }
            for(i=min-1; i<m; i++){
                k=nd.loc[i];
                xx=(k-1)/n;
                yy=(k-1)%n;
                a[xx][yy]=0;
                for(j=0; j<4; j++){
                    x=xx; y=yy;
                    if(j==0)
                        x--;
                    else if(j==1)
                        x++;
                    else if(j==2)
                        y--;
                    else if(j==3)
                        y++;
                    if(x>=0 && x<n && y>=0 && y<n && a[x][y]==0)
                    if((x==0 || a[x-1][y]==0) && (y==0 || a[x][y-1]==0) && (x==n-1 || a[x+1][y]==0) && (y==n-1 || a[x][y+1]==0)){
                        nd2=nd;
                        nd2.loc[i]=x*n+y+1;
                        t=0;
                        if(i==min-1 && x*n+y+1==exitloc) {nd2.loc[i]=0; t=1;}
                        num2=trans(nd2,m);
                        if(check[num2]>0) continue;
                        check[num2]=check[nd.num]+1;
                        nd2.num=num2;
                        nd2.t=nd.t-t;
                        nd2.f=H(nd2)+check[nd2.num];
                        Q.push(nd2);
                    }
                }
                a[xx][yy]=i+1;
            }
            for(i=0; i<m; i++){
                k=nd.loc[i];
                if(k==0) continue;
                a[(k-1)/n][((k-1)%n)]=0;
            }
        }
    }
    
    int main()
    {
        int T,i,j,k;
        char s[10],ch;
        node nd;
        cin>>T;
        while(T--) {
            scanf("%d %d",&n,&m);
            while(!Q.empty())Q.pop();
            mod=n*n+1;
            gets(s);
            for(i=0; i<n; i++)
            {
                gets(s);
                for(j=0; j<n; j++)
                    if(s[j]=='x')
                        exitloc = i*n + j + 1;
                    else if(s[j]>='1' && s[j]<='0'+m)
                        nd.loc[s[j]-'1'] = i*n + j + 1;
            }
            ini(n,m);
            k=trans(nd,m);
            check[k]=1;
            nd.num=k;
            nd.f=H(nd)+check[nd.num];
            nd.t=m;
            Q.push(nd);
            BFS();
            printf("%d\n",check[0]-1);
        }
        return 0;
    }

     

  • 相关阅读:
    bash脚本编程之数组和字符串处理
    Linux启动流程简介以及各启动阶段失败的恢复方法
    Linux路由表的重要性以及配置
    Linux终端和伪终端简述
    Linux九阴真经之无影剑残卷9(Shell脚本编程进阶)
    Linux九阴真经之无影剑残卷8(计划任务)
    Linux九阴真经之无影剑残卷7(进程管理)
    Linux九阴真经之无影剑残卷5(Linux静态路由的实现)
    Linux九阴真经之无影剑残卷4(创建虚拟内存--swap)
    Linux九阴真经之无影剑残卷3(将home目录搬到新分区)
  • 原文地址:https://www.cnblogs.com/Lattexiaoyu/p/2507989.html
Copyright © 2020-2023  润新知