• HDU 4531 吉哥系列故事——乾坤大挪移 (BFS)


    吉哥系列故事——乾坤大挪移

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
    Total Submission(s): 184    Accepted Submission(s): 50


    Problem Description
      只有进入本次马拉松复赛,你才有机会知道一个秘密:吉哥的真名叫基哥,江湖人称“叽叽哥”。

      叽叽哥除了编程,还一直有个武侠梦,他最喜欢的人物是金庸小说《倚天屠龙记》中的张无忌,不仅有美人环绕,而且有一身的好武功,尤其是那神秘的乾坤大挪移,让他梦寐以求:
      
      “乾坤大挪移乃在颠倒一刚一柔、一阴一阳的乾坤二气,随意而行,不用心而无不心用,所谓至我逍遥游,以纯阳之身,和纯阴之体,合练双修,不动身,只用意,意动身守......”
      
      但是,梦毕竟只是梦,平时在编程的空闲时间,叽叽哥也最多只能上网玩一下名为“乾坤大挪移”的游戏聊以自慰而已。
      这个“乾坤大挪移”游戏是在3*3的方格中进行。
      游戏的目标是通过移动,让相同颜色的块形成一个连通块(相邻是指两个块有边相邻,角相邻不算)。
      移动规则如下:选择一行(列),向左右(上下)移动一格,方格从一边划出,则从对应的另外一边划入,像履带一样。
      如选择第一行向右边移动,最右边的那格会移动到最左边。
      游戏中还有一些方格被固定住,这些方格没办法移动(如下图的第三行第二列)。
      下图是游戏的一个演示(即Case 1):



      假设现在告诉你初始状态,请问你最少需要几步才能达到目标?
     
    Input
    第一行一个整数T代表接下去有T组数据;
    每组数据由3*3的模块组成,每个模块表示的小正方形是由上下左右四个小三角形组成;
    每个模块有5个字符,前四个字符分别表示组成正方形的上下左右四个小三角形的颜色,第五个字符表示该格子能否移动(0表示能移动,1表示不能移动).

    [Technical Specification]
    0<T<=100
    代表颜色的字符一定是RGBO的其中一个
    代表能否移动移动的字符一定是0或者1
     
    Output
    首先输出case数,接着输出最小的移动步数使得游戏达到目标状态(见sample);
    数据保证有解。
     
    Sample Input
    2 GGGG0 GGGG0 GGGG0 OGOO0 GGGG0 OGOO0 OOOO0 OGGG1 OOOO0 RRRR0 OOOO0 OOOO0 OOOO0 OOOO0 OOOO0 OOOO0 OOOO0 RRRR0
     
    Sample Output
    Case #1: 5 Case #2: 2
     
    Source
     
    Recommend
    liuyiding

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4531

    这题很明显就是bfs。

    但是比赛的时候被坑死了,错了无数次。

    用string就超时,只能改成char了,看来string慢很多啊。

    我是用int表示状态的,初始状态就是012345678.这样用个map就可以对状态判重了。

    至于判断是不是符合题意的状态,我用的是并查集来判断的。每个格子上下左右四个三角标号0、1、2、3.这样总共4*9=36个点。根据情况去合并,最后判断相同颜色是不是根相同即可。合并的时候,一个格子里的四条边可能合并,格子间12条边可能合并。

    状态转移就是6种情况。分别对每一行、每一列操作。。

    这题写挫了要么MLE,要么TLE,很难搞。。。。。。

    /*
    *HDU 4531
    *BFS
    *注意判重
    */
    
    
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <map>
    #include <set>
    #include <string>
    #include <queue>
    #include <iostream>
    using namespace std;
    
    char str[3][3][6];
    char g[3][3][6];
    
    map<int,int>mp;
    queue<int>q;
    bool move[6];//是否可以移动,0~5对应1~3行,1~3列
    
    //并查集判断连通
    int F[50];
    int find(int x)
    {
        if(F[x]==-1)return x;
        return F[x]=find(F[x]);
    }
    void bing(int x,int y)
    {
        int t1=find(x);
        int t2=find(y);
        if(t1!=t2)F[t1]=t2;
    }
    //并查集判断是不是连通
    bool judge(int state)//判断状态state是不是连通
    {
        char temp[10];
        int t[10];
        sprintf(temp,"%09d",state);
        for(int i=0;i<9;i++)t[i]=temp[i]-'0';
        for(int i=0;i<3;i++)
          for(int j=0;j<3;j++)
          {
              int p=t[3*i+j];
              int x=p/3;
              int y=p%3;
              strcpy(g[i][j],str[x][y]);
          }
        memset(F,-1,sizeof(F));
        for(int i=0;i<3;i++)
          for(int j=0;j<3;j++)
          {
              if(g[i][j][0]==g[i][j][2])bing(12*i+4*j,12*i+4*j+2);
              if(g[i][j][0]==g[i][j][3])bing(12*i+4*j,12*i+4*j+3);
              if(g[i][j][1]==g[i][j][2])bing(12*i+4*j+1,12*i+4*j+2);
              if(g[i][j][1]==g[i][j][3])bing(12*i+4*j+1,12*i+4*j+3);
          }
        for(int i=0;i<3;i++)
        {
            if(g[i][0][3]==g[i][1][2])bing(12*i+3,12*i+4+2);
            if(g[i][1][3]==g[i][2][2])bing(12*i+4+3,12*i+8+2);
        }
        for(int j=0;j<3;j++)
        {
            if(g[0][j][1]==g[1][j][0])bing(4*j+1,12+4*j+0);
            if(g[1][j][1]==g[2][j][0])bing(12+4*j+1,24+4*j+0);
        }
        int R=-1,G=-1,B=-1,O=-1;
        for(int i=0;i<3;i++)
          for(int j=0;j<3;j++)
            for(int k=0;k<4;k++)
            {
                int t1=find(12*i+4*j+k);
                if(g[i][j][k]=='R')
                {
                    if(R==-1)R=t1;
                    else if(t1!=R)return false;
                }
                else if(g[i][j][k]=='G')
                {
                    if(G==-1)G=t1;
                    else if(t1!=G)return false;
                }
                else if(g[i][j][k]=='B')
                {
                    if(B==-1)B=t1;
                    else if(t1!=B)return false;
                }
                else
                {
                    if(O==-1)O=t1;
                    else if(t1!=O)return false;
                }
            }
        return true;
    }
    int bfs()
    {
        mp.clear();
        while(!q.empty())q.pop();
        int tmp,now;
        char ss1[10],ss2[10];
        tmp=12345678; //初始是012345678
        mp[tmp]=0;
        q.push(tmp);
        while(!q.empty())
        {
            tmp=q.front();
            q.pop();
            if(judge(tmp))return mp[tmp];
            sprintf(ss1,"%09d",tmp);
    
            for(int i=0;i<3;i++)
              for(int j=0;j<3;j++)
              {
                  int t=ss1[3*i+j]-'0';
                 strcpy(g[i][j],str[t/3][t%3]);
              }
            //第一行的左右移动
            if(move[0])
            {
                strcpy(ss2,ss1);
                ss2[0]=ss1[1];
                ss2[1]=ss1[2];
                ss2[2]=ss1[0];
                now=0;
                for(int i=0;i<9;i++)
                {
                    now*=10;
                    now+=ss2[i]-'0';
                }
                if(mp.find(now)==mp.end())
                {
                    mp[now]=mp[tmp]+1;
                    q.push(now);
                }
    
                ss2[0]=ss1[2];
                ss2[1]=ss1[0];
                ss2[2]=ss1[1];
                now=0;
                for(int i=0;i<9;i++)
                {
                    now*=10;
                    now+=ss2[i]-'0';
                }
                if(mp.find(now)==mp.end())
                {
                    mp[now]=mp[tmp]+1;
                    q.push(now);
                }
    
            }
    
            //第二行的左右移动
            if(move[1])
            {
                strcpy(ss2,ss1);
                ss2[3]=ss1[4];
                ss2[4]=ss1[5];
                ss2[5]=ss1[3];
                now=0;
                for(int i=0;i<9;i++)
                {
                    now*=10;
                    now+=ss2[i]-'0';
                }
                if(mp.find(now)==mp.end())
                {
                    mp[now]=mp[tmp]+1;
                    q.push(now);
                }
                ss2[3]=ss1[5];
                ss2[4]=ss1[3];
                ss2[5]=ss1[4];
                now=0;
                for(int i=0;i<9;i++)
                {
                    now*=10;
                    now+=ss2[i]-'0';
                }
                if(mp.find(now)==mp.end())
                {
                    mp[now]=mp[tmp]+1;
                    q.push(now);
                }
            }
    
    
            //第三行的左右移动
            if(move[2])
            {
                strcpy(ss2,ss1);
                ss2[6]=ss1[7];
                ss2[7]=ss1[8];
                ss2[8]=ss1[6];
                now=0;
                for(int i=0;i<9;i++)
                {
                    now*=10;
                    now+=ss2[i]-'0';
                }
                if(mp.find(now)==mp.end())
                {
                    mp[now]=mp[tmp]+1;
                    q.push(now);
                }
    
                ss2[6]=ss1[8];
                ss2[7]=ss1[6];
                ss2[8]=ss1[7];
                now=0;
                for(int i=0;i<9;i++)
                {
                    now*=10;
                    now+=ss2[i]-'0';
                }
                if(mp.find(now)==mp.end())
                {
                    mp[now]=mp[tmp]+1;
                    q.push(now);
                }
    
            }
    
    
            //第一列的左右移动
            if(move[3])
            {
                strcpy(ss2,ss1);
                ss2[0]=ss1[3];
                ss2[3]=ss1[6];
                ss2[6]=ss1[0];
                now=0;
                for(int i=0;i<9;i++)
                {
                    now*=10;
                    now+=ss2[i]-'0';
                }
                if(mp.find(now)==mp.end())
                {
                    mp[now]=mp[tmp]+1;
                    q.push(now);
                }
    
                ss2[0]=ss1[6];
                ss2[3]=ss1[0];
                ss2[6]=ss1[3];
                now=0;
                for(int i=0;i<9;i++)
                {
                    now*=10;
                    now+=ss2[i]-'0';
                }
                if(mp.find(now)==mp.end())
                {
                    mp[now]=mp[tmp]+1;
                    q.push(now);
                }
    
            }
    
            //第二列的左右移动
            if(move[4])
            {
                strcpy(ss2,ss1);
                ss2[1]=ss1[4];
                ss2[4]=ss1[7];
                ss2[7]=ss1[1];
                now=0;
                for(int i=0;i<9;i++)
                {
                    now*=10;
                    now+=ss2[i]-'0';
                }
                if(mp.find(now)==mp.end())
                {
                    mp[now]=mp[tmp]+1;
                    q.push(now);
                }
    
                ss2[1]=ss1[7];
                ss2[4]=ss1[1];
                ss2[7]=ss1[4];
                now=0;
                for(int i=0;i<9;i++)
                {
                    now*=10;
                    now+=ss2[i]-'0';
                }
                if(mp.find(now)==mp.end())
                {
                    mp[now]=mp[tmp]+1;
                    q.push(now);
                }
    
            }
    
            //第三列的左右移动
            if(move[5])
            {
                strcpy(ss2,ss1);
                ss2[2]=ss1[5];
                ss2[5]=ss1[8];
                ss2[8]=ss1[2];
                now=0;
                for(int i=0;i<9;i++)
                {
                    now*=10;
                    now+=ss2[i]-'0';
                }
                if(mp.find(now)==mp.end())
                {
                    mp[now]=mp[tmp]+1;
                    q.push(now);
                }
    
                ss2[2]=ss1[8];
                ss2[5]=ss1[2];
                ss2[8]=ss1[5];
                now=0;
                for(int i=0;i<9;i++)
                {
                    now*=10;
                    now+=ss2[i]-'0';
                }
                if(mp.find(now)==mp.end())
                {
                    mp[now]=mp[tmp]+1;
                    q.push(now);
                }
            }
    
        }
        return -1;
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        int iCase=0;
        while(T--)
        {
            iCase++;
            printf("Case #%d: ",iCase);
            for(int i=0;i<6;i++)move[i]=true;
            for(int i=0;i<3;i++)
              for(int j=0;j<3;j++)
              {
                  scanf("%s",&str[i][j]);
                  if(str[i][j][4]=='1')//所在的列和行不能移动
                  {
                      move[i]=false;
                      move[3+j]=false;
                  }
              }
            printf("%d\n",bfs());
        }
        return 0;
    }
    人一我百!人十我万!永不放弃~~~怀着自信的心,去追逐梦想
  • 相关阅读:
    2016/3/10 Java 错题
    2016/3/9 Java 错题集
    Java Socket 编程实验总结
    CSU 1290
    CSU 1307
    CSU 1060
    Problem B SPOJ DCEPC11I
    activemq 学习系列(二) 常用配置
    activemq 学习系列(一) 详细入门使用
    MySql 用户创建与授权
  • 原文地址:https://www.cnblogs.com/kuangbin/p/2990176.html
Copyright © 2020-2023  润新知