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):

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


  假设现在告诉你初始状态,请问你最少需要几步才能达到目标?
 

 

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;

}

 

 

 

你可能感兴趣的:(HDU)