zoukankan      html  css  js  c++  java
  • 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;
    }
    人一我百!人十我万!永不放弃~~~怀着自信的心,去追逐梦想
  • 相关阅读:
    今天开始用 VSU 2010
    Visual Studio 2010 模型设计工具 基本应用
    Asp.Net访问Oracle 数据库 执行SQL语句和调用存储过程
    Enterprise Library 4.1 Security Block 快速使用图文笔记
    解决“System.Data.OracleClient 需要 Oracle 客户端软件 8.1.7 或更高版本。”(图)
    一个Oracle存储过程示例
    Enterprise Library 4.1 Application Settings 快速使用图文笔记
    Oracle 10g for Windows 简体中文版的安装过程
    Oracle 11g for Windows 简体中文版的安装过程
    Oracle 9i 数据库 创建数据库 Net 配置 创建表 SQL查询 创建存储过程 (图)
  • 原文地址:https://www.cnblogs.com/kuangbin/p/2990176.html
Copyright © 2011-2022 走看看