zoukankan      html  css  js  c++  java
  • 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;
    }

     

  • 相关阅读:
    游戏与微博的结合,一个微博后台与前端的设计(基于mysql)。(一)
    UDK 学习点滴 (不断更新)
    多语言版本与UI的展现问题
    用dx11检查你的硬件设备中有几个适配器(adapter)
    多重采样与dx11检查硬件多重采样能力的API
    不均匀点香求时间的问题解
    图片内包含文本制作方法
    vim 搜索 向上 向下 取消高亮
    解决Ucenter 头像上传小收获
    不知道是什么意思
  • 原文地址:https://www.cnblogs.com/Lattexiaoyu/p/2507989.html
Copyright © 2011-2022 走看看