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】

  • 相关阅读:
    Integer中计算int位数的方法
    Spark学习---常见的RDD转和行动操作
    Spark学习---RDD编程
    《教父》中的经典台词以及英文原版
    关于MATSIM中,如何关闭自动加载dtd的问题
    源发行版8需要目标发行版1.8
    关于Mysql中GROUP_CONCAT函数返回值长度的坑
    【转】通过xml处理sql语句时对小于号与大于号的处理转换
    XmlDocument根据节点的属性值获取节点
    【转】使用SevenZipSharp压缩、解压文件
  • 原文地址:https://www.cnblogs.com/zhazhaacmer/p/8497094.html
Copyright © 2011-2022 走看看