hdu 4531(模拟+BFS+DFS)

比较烦人的一道题目,看着题目都觉得很吓人,不过模拟题终究是模拟题, 耐心点还是可以过的。

题意: 给出了一个3*3的方块,每个方块有上下左右四个颜色, 然后每次可以在一行上 左/右循环移一格, 或一列上  上/下循环移一格。 求最少操作次数使的3*3中相同颜色的块形成一个连通块。

因为只有9个方块,所以最多的状态数为9! , 10^6次方的复杂度还是可以接受的。

然后就是一系列比较复杂的变换,搜索。 耐心点还是没有问题的。

写了几个小时  ,1 A

 

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

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


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

 

 
#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
#include <iostream>
using namespace std;
#define INF 0x3fffffff

struct node
{
    char up,dn,ri,lt;
    int id;
}g[3][3];

struct ss
{
    node k[3][3];
};

int mi;
int sign[2][3]; // 表示那些操作不能进行
bool mark[10001000];
int mark1[3][3][4];
int save[11]={1,1,2,6,24,120,720,5040,40320,362880,3628800};
queue<ss>  que[2];


int cantuo(node s[3][3])
{
    int ct[10];
    int cnt=1;
    for(int i=0;i<3;i++)
        for(int j=0;j<3;j++)
            ct[cnt++]=s[i][j].id;
    int sum=0;
    for(int i=1;i<=9;i++)
    {
        cnt=0;
        for(int j=i+1;j<=9;j++)
            if(ct[i]>ct[j]) cnt++;
        sum+=save[9-i]*cnt;
    }
    return sum;
}

int change(char c)
{
    if(c=='R') return 0;
    if(c=='G') return 1;
    if(c=='B') return 2;
    return 3;
}

int dfs(int x,int y,int flag,char key,node s[3][3])
{
    int cnt=0;
    if(flag==0||flag==1)
    {
        if(s[x][y].lt == key&&mark1[x][y][3]==0)
        {
            mark1[x][y][3]=1;
            cnt+=dfs(x,y,3,key,s);
        }
        if(s[x][y].ri == key&&mark1[x][y][2]==0)
        {
            mark1[x][y][2]=1;
            cnt+=dfs(x,y,2,key,s);
        }
    }
    else
    {
        if(s[x][y].up==key&&mark1[x][y][0]==0)
        {
            mark1[x][y][0]=1;
            cnt+=dfs(x,y,0,key,s);
        }
        if(s[x][y].dn==key&&mark1[x][y][1]==0)
        {
            mark1[x][y][1]=1;
            cnt+=dfs(x,y,1,key,s);
        }
    }
    if(flag==0&&x!=0&&s[x-1][y].dn==key && mark1[x-1][y][1]==0)
    {
        mark1[x-1][y][1]=1;
        cnt+=dfs(x-1,y,1,key,s);
    }
    if(flag==1&&x!=2&&s[x+1][y].up==key && mark1[x+1][y][0]==0)
    {
        mark1[x+1][y][0]=1;
        cnt+=dfs(x+1,y,0,key,s);
    }
    if(flag==2&&y!=2&&s[x][y+1].lt==key && mark1[x][y+1][3]==0)
    {
        mark1[x][y+1][3]=1;
        cnt+=dfs(x,y+1,3,key,s);
    }
    if(flag==3&&y!=0&&s[x][y-1].ri==key&&mark1[x][y-1][2]==0)
    {
        mark1[x][y-1][2]=1;
        cnt+=dfs(x,y-1,2,key,s);
    }
    return cnt+1;
}    

int check(node s[3][3]) // 比较关键的一步,判断是否联通.
{
    memset(mark1,0,sizeof(mark1));
    int tmark[4];
    memset(tmark,0,sizeof(tmark)); // R=0,G=1,B=2,O=3;
    int sum=0;
    // up 0, dn 1, ri 2,lt 3
    for(int i=0;i<3;i++)
        for(int j=0;j<3;j++)
        {
            if( tmark[change(s[i][j].up)]==0 )
            {
                tmark[change(s[i][j].up)]=1;
                mark1[i][j][0]=1;
                sum+=dfs(i,j,0,s[i][j].up,s);
            }
            if (tmark[change(s[i][j].dn)]==0 )
            {
                tmark[change(s[i][j].dn)]=1;
                mark1[i][j][1]=1;
                sum+=dfs(i,j,1,s[i][j].dn,s);
            }
            if (tmark[change(s[i][j].ri)]==0)
            {
                tmark[change(s[i][j].ri)]=1; 
                mark1[i][j][2]=1;
                sum+=dfs(i,j,2,s[i][j].ri,s);
            }
            if (tmark[change(s[i][j].lt)]==0)
            {
                tmark[change(s[i][j].lt)]=1;
                mark1[i][j][3]=1;
                sum+=dfs(i,j,3,s[i][j].lt,s);
            }
        }
    if(sum==9*4) return 1;
    else return 0;
}

void print(node s[3][3])
{
    printf("##############\n");
    for(int i=0;i<3;i++)
    {
        for(int j=0;j<3;j++)
        {
            printf("%d ",s[i][j].id);
        }
        printf("\n");
    }
    printf("##################\n");
}

int bfs()
{
    memset(mark,0,sizeof(mark));
    int a=0,b=1;
    while(que[0].size()!=0) que[0].pop();
    while(que[1].size()!=0) que[1].pop(); //清空
    ss ts;
    for(int i=0;i<3;i++)
        for(int j=0;j<3;j++)
            ts.k[i][j]=g[i][j];
    que[0].push(ts);
    int tmp=cantuo(g);
    mark[tmp]=1;
    int cnt=-1;
    ss cur,nwnode;
    node tnode;
    while(que[a].size()!=0)
    {
        cnt++;
        swap(a,b);
        while(que[b].size()!=0)
        {
            cur=que[b].front();
            que[b].pop();
            if(check(cur.k)==1)
            {
                return cnt;
            }
            //nwnode=cur;
            for(int i=0;i<3;i++)
            {
                if(sign[0][i]==1) continue;
                
                //print(cur.k);
                tnode=cur.k[i][0];
                cur.k[i][0]=cur.k[i][1];
                cur.k[i][1]=cur.k[i][2];
                cur.k[i][2]=tnode;

                //print(cur.k);
                int id=cantuo(cur.k);
                if(mark[id]==0)
                {
                    mark[id]=1;
                    que[a].push(cur);
                }
                tnode=cur.k[i][0];
                cur.k[i][0]=cur.k[i][2];
                cur.k[i][2]=cur.k[i][1];
                cur.k[i][1]=tnode; // 恢复了
                
                //print(cur.k);
                //////////////////////////////
                tnode=cur.k[i][0];
                cur.k[i][0]=cur.k[i][2];
                cur.k[i][2]=cur.k[i][1];
                cur.k[i][1]=tnode;
                
                //print(cur.k);
                id=cantuo(cur.k);
                if(mark[id]==0)
                {
                    mark[id]=1;
                    que[a].push(cur);
                }
                tnode=cur.k[i][0];
                cur.k[i][0]=cur.k[i][1];
                cur.k[i][1]=cur.k[i][2];
                cur.k[i][2]=tnode;
                
                //print(cur.k);
            }
            for(int i=0;i<3;i++)
            {
                if(sign[1][i]==1) continue;
                tnode=cur.k[0][i];
                cur.k[0][i]=cur.k[1][i];
                cur.k[1][i]=cur.k[2][i];
                cur.k[2][i]=tnode;
                int id=cantuo(cur.k);
                if(mark[id]==0)
                {
                    mark[id]=1;
                    que[a].push(cur);
                }
                tnode=cur.k[0][i];
                cur.k[0][i]=cur.k[2][i];
                cur.k[2][i]=cur.k[1][i];
                cur.k[1][i]=tnode;
                /////////////////
                tnode=cur.k[0][i];
                cur.k[0][i]=cur.k[2][i];
                cur.k[2][i]=cur.k[1][i];
                cur.k[1][i]=tnode;
                id=cantuo(cur.k);
                if(mark[id]==0)
                {
                    mark[id]=1;
                    que[a].push(cur);
                }
                tnode=cur.k[0][i];
                cur.k[0][i]=cur.k[1][i];
                cur.k[1][i]=cur.k[2][i];
                cur.k[2][i]=tnode;
            }
        }
    }
}

int main()
{
    int tt=1;
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(sign,0,sizeof(sign));
        char str[10];
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
            {
                scanf("%s",str);
                g[i][j].up=str[0];
                g[i][j].dn=str[1];
                g[i][j].lt=str[2];
                g[i][j].ri=str[3];
                g[i][j].id=i*3+j;
                if(str[4]=='1')
                {
                    sign[0][i]=1;
                    sign[1][j]=1; // 涉及到这个格子的操作都不能进行.
                }
            }

        printf("Case #%d: %d\n",tt++,bfs());
    }
    return 0;
}

 

 

posted @ 2013-03-30 17:29  chenhuan001  阅读(194)  评论(0编辑  收藏  举报