zoukankan      html  css  js  c++  java
  • 胡搞-强化版的light oj-1055-的思路-AI版的6重暴力For循环的BFS

    新题目大意:

      三个棋子按照先后顺序,可以随意方向合法地走到空位置上(而不是像原题light oj-1055中的一样三个棋子每次走的方向都一致),当三个棋子全部走进目标地点,就结束;求需要指挥的最少次数。

    思路:

      BFS

      在每次进行指挥时,需要分别指挥三个棋子,每个棋子至多有五种走法(第五种为原地不动——因为前进时受阻没法动的时候),同时枚举三个棋子的当前位置进入队列中。由于每个棋子在走的时候会影响到后续的点的移动,故需要三重for循环来枚举每次三个点的移动先后顺序,然后依旧三重循环来枚举搞定三个点的移动方向,然后判断-标记-加入队列?结束。

    标记去重的BFS思路:
      三个棋子共同组成的局面可以不分先后相互等价;用vis[A.x][A.y][B.x][B.y][C.x][C.y]来进行标记!
      所以对于每一个局面,都有其余5个分先后的局面与其等价。即ABC=ACB=BAC=BCA=CAB=CBA.
    /* 
    4
    ..A.
    XXXB
    ..C.
    ....
    /*或许可以再加一个优先队列优化一下时间:排序标准是三个点与三个终点的最小距离之和;或许还可以再加一个剪枝的方法:每次搜索一个点时需要枚举四个方位,可以事先统计所有空点周围不是的‘#’的方向数量,当每个点可以作出的选择数等于上述点数就continue。*/
    //下面 极大值测试3.9s(Tmax==50),
    1
    9
    AB....C..
    .........
    .........
    .........
    .........
    .........
    .........
    .........
    X..X..X..
     
    */
     
    胡搞的代码:
    #define 其余头文件...
    #define N 10
    #define inf 0x3f3f3f3f
    char mp[N][N];
    int n;
    struct node{
        int x,y;
    }just;
    struct group{//一个局面三个点的位置,位置之间等价
        node p[3];//0,1,2三位有效存储
        int step;
    }st;
    int dir[5][2]={{0,0},{1,0},{0,1},{0,-1},{-1,0} };
    bool vis[N][N][N][N][N][N];//标记数组,模拟每一组棋子组合成的局面
    bool judge_end(group x){  //判断当前局面是否达到结束要求
        int num=0;
        for(int i=0;i<3;i++){
                if(mp[x.p[i].x][x.p[i].y]=='X')
                    num++;
        }
        if(num==3)return true;
        return false;
    }
    void getvis(group a){//从一个局面获取6个标记
        vis[a.p[0].x][a.p[0].y][a.p[1].x][a.p[1].y][a.p[2].x][a.p[2].y]=true;
        vis[a.p[0].x][a.p[0].y][a.p[2].x][a.p[2].y][a.p[1].x][a.p[1].y]=true;
        vis[a.p[1].x][a.p[1].y][a.p[0].x][a.p[0].y][a.p[2].x][a.p[2].y]=true;
        vis[a.p[1].x][a.p[1].y][a.p[2].x][a.p[2].y][a.p[0].x][a.p[0].y]=true;
        vis[a.p[2].x][a.p[2].y][a.p[1].x][a.p[1].y][a.p[0].x][a.p[0].y]=true;
        vis[a.p[2].x][a.p[2].y][a.p[0].x][a.p[0].y][a.p[1].x][a.p[1].y]=true;
    }
    bool getstep(int i,int k,group a){//i表示第i个点的下一步操作,向dir[k]进行下一步
        node s=a.p[i];
        s.x=s.x+dir[k][0];
        s.y=s.y+dir[k][1];
        if(s.x>=n||s.y>=n||s.x<0||s.y<0)return false;//越界,‘#’,走到同一局面其他点上, false
        if(mp[s.x][s.y]=='#')return false;
        for(int j=0;j<=2;j++){
            if(i!=j&&(a.p[j].x==s.x)&&(a.p[j].y==s.y))
                return false;
        }
        just=s;//存储的全局变量
        return true;
    }
    void debug(group a){
        printf("*%dstep* *A*(%d,%d) ",a.step,a.p[0].x,a.p[0].y);
        printf("*B*(%d,%d) ",a.p[1].x,a.p[1].y);
        printf("*C*(%d,%d)
    ",a.p[2].x,a.p[2].y);
    }
    int bfs(){
        memset(vis,false,sizeof(vis));
        group now,ne,ne2,ne3;
        queue<group>Q;
        st.step=0;
        Q.push(st); //标记起点局面
        getvis(st);
        while(Q.size()){
            now=Q.front();
            Q.pop();
            if(judge_end(now))return now.step;
                //按ABC,ACB,BAC,BCA,CAB,CBA六种先后方式来枚举,i-j-k三重循环
            for(int i=0;i<3;i++){//枚举第一个先走的编号
                for(int j=0;j<3;j++){//枚举第二个编号
                    for(int k=0;k<3;k++){//第三个
                       if(j==i||i==k||j==k)continue;
    
                       for(int x=0;x<5;x++){  //x-y-z三种循环分别表示i-j-k的走位方向
                            ne=now;
                            if(getstep(i,x,ne)==false)continue;
                            else ne.p[i]=just;
                         for(int y=0;y<5;y++){
                             ne2=ne;
                            if(getstep(j,y,ne2)==false)continue;
                            else ne2.p[j]=just;
                                 for(int z=0;z<5;z++){
                                     ne3=ne2;
                                     if(getstep(k,z,ne3)==false)continue;
                                     else ne3.p[k]=just;
                                //在这里得到了合格的next3局面,然后进行判断
                                if(vis[ne3.p[0].x][ne3.p[0].y][ne3.p[1].x][ne3.p[1].y][ne3.p[2].x][ne3.p[2].y]==true)
                                    continue;//重复走过了
                                ne3.step=now.step+1;
                             //   debug(ne3);
                                getvis(ne3);//进行标记
                                if(judge_end(ne3)){
                                 //   printf("--up|------now :");debug(now);
                                    return ne3.step;
                                }
                                else
                                    Q.push(ne3);
                            }
                        }
                       }
                    }
                }
            }
        }
        return -1;
    }
    int main()
    {
        int T,cas=0;
        scanf("%d",&T);
        while(T--){
            scanf("%d",&n);
            for(int i=0;i<n;i++)//读图
                scanf("%s",mp[i]);
            int num1=0;
            for(int i=0;i<n;i++){
                for(int j=0;j<n;j++){
                    if(mp[i][j]>='A'&&mp[i][j]<='C')
                        st.p[num1].x=i,st.p[num1++].y=j;
                }
            }
            printf("Case %d: ",++cas);
            int ans=bfs();
            if(ans!=-1)
                printf("%d
    ",ans);
            else
                printf("trapped
    ");
        }
    
        return 0;
    }
    View Code

    上一篇:【loj-1055-Going Together-三个棋子推箱子走到目的地--讲预判的bfs】

  • 相关阅读:
    Linq聚合操作之Aggregate,Count,Sum,Distinct源码分析
    Linq分区操作之Skip,SkipWhile,Take,TakeWhile源码分析
    Linq生成操作之DefautIfEmpty,Empty,Range,Repeat源码分析
    Linq基础操作之Select,Where,OrderBy,ThenBy源码分析
    PAT 1152 Google Recruitment
    PAT 1092 To Buy or Not to Buy
    PAT 1081 Rational Sum
    PAT 1084 Broken Keyboard
    PAT 1077 Kuchiguse
    PAT 1073 Scientific Notation
  • 原文地址:https://www.cnblogs.com/zhazhaacmer/p/8497094.html
Copyright © 2011-2022 走看看