Dearboy's Puzzle



Description

Dearboy is a game lover. Recently, he loves playing the game Lian Lian Kan. This game is played on a board with N*M grids, and lots of cards are put on the board in the grids. You should find a pair of the same cards, if not more than three segments can link this pair without passing any other cards, you can take this pair away from the board. (You may be puzzled about the meaning of not more than 3 segments, just refer to the figure below, in which we express some allowable links). Continue the process above, if you can clear all the cards, you win the game, otherwise you lose it.

If you have played this game, you may know that sometimes the game has no solution and you are sure to lose. Dearboy is very boring about the games without solutions, so he asks you, a famous programmer, to tell him whether he can win the giving game phase or not.

Input

The input consists of multiple test cases. The first line of each test case contains two integers N and M (2 <= N, M <= 10), which denote the sizes of the game board. The next N lines give the board layout, with each line containing M characters. A character is one of the following: ‘*’ (an empty position), ‘A’, ‘B’, ‘C’, ’D’ (the cards, which imply that there are at most 4 different kinds of cards). Different letters represent different cards. The number of same cards may be odd, and there may be more than one pair of the same cards.

The input is terminated with two 0's. This test case shoud not be processed.

Output

For each test case, print in one line "yes" if Dearboy can win the game, "no" otherwise.

Sample Input

6 8
********
*A**C***
**B*****
***B*D**
****D***
********
2 2
AB
BA
6 8
***A****
*A**C***
**B***C*
***B*D**
****D***
********
0 0

Sample Output

no
no
yes
 
  
 
  
 
  
具体做法是,dfs寻找要消去的格子,然后bfs找出这个格子能与哪个相同内容的格子连起来,如果能连起来,调用前面的的dfs。
如果出现

..AB.. ..BA..

且此时A,B均只剩两个,直接返回false

另外还有几个可以剪的地方,如果对于某个case,某种格子有奇数个,直接输出no

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<queue>
using namespace std;
struct Node
{
    int x,y,se,d,c;
};
queue<Node> Q;
int move[4][2]= {-1,0,1,0,0,-1,0,1};
int vis[11][11],mat[11][11],card[4],flag,N,M;
char Map[11][11];
int ok(int x,int y,int c)
{
    if(!(x>=0&&x<N&&y>=0&&y<M)) return 0;
    if(mat[x][y]!=-1&&mat[x][y]!=c) return 0;
    return 1;
}
int isAB(int a,int b)
{
    for(int i=0; i<N; i++)
        for(int j=0; j<M; j++)
        {
            if(mat[i][j]==a)
            {
                if(mat[i+1][j+1]==a&&mat[i][j+1]==b&&mat[i+1][j]==b)
                    return 1;
                return 0;
            }
            if(mat[i][j]==b)
            {
                if(mat[i+1][j+1]==b&&mat[i][j+1]==a&&mat[i+1][j]==a)
                    return 1;
                return 0;
            }
        }
}
int cut()
{
    for(int i=0; i<4; i++)
        for(int j=i+1; j<4; j++)
            if(card[i]==card[j]&&card[i]==2)
                if(isAB(i,j)) return 1;
    return 0;
}

int dfs(int count)
{
    if(!count) return flag=1;
    if(cut()) return 0;
    for(int i=0; i<N; i++)
        for(int j=0; j<M; j++)
        {
            if(flag) return 1;
            if(mat[i][j]!=-1)
            {
                int c=mat[i][j];
                int pos[10][2],cnt=0;
                memset(vis,0,sizeof(vis));
                Node nt,nt1;
                nt.x=i;
                nt.y=j;
                nt.c=-1;
                nt.se=0;
                nt.d=-1;
                vis[i][j]=1;
                Q.push(nt);
                while(!Q.empty())
                {
                    nt=Q.front();
                    Q.pop();
                    if(nt.c==c)
                    {
                        pos[cnt][0]=nt.x;
                        pos[cnt][1]=nt.y;
                        cnt++;
                        continue;
                    }
                    for(int k=0; k<4; k++)
                    {
                        int x=nt.x+move[k][0],y=nt.y+move[k][1];
                        if(ok(x,y,c)&&!vis[x][y])
                        {
                            if(nt.d==k || nt.d==-1) nt1.se=nt.se;
                            else nt1.se=nt.se+1;
                            if(nt1.se<=2)
                            {
                                nt1.x=x;
                                nt1.y=y;
                                nt1.c=mat[x][y];
                                nt1.d=k;
                                vis[x][y]=1;
                                Q.push(nt1);
                            }
                        }
                    }
                }
                mat[i][j]=-1;
                card[c]-=2;
                for(int k=0; k<cnt; k++)
                {
                    if(flag) return 1;
                    int x=pos[k][0],y=pos[k][1];
                    mat[x][y]=-1;
                    dfs(count-2);
                    mat[x][y]=c;
                }
                mat[i][j]=c;
                card[c]+=2;
            }
        }
    return 0;
}
int main()
{
    while(scanf("%d%d",&N,&M)&&N&&M)
    {
        memset(card,0,sizeof(card));
        memset(mat,-1,sizeof(mat));
        int count=0;
        flag=1;
        for(int i=0; i<N; i++)
            scanf("%s",Map[i]);
        for(int i=0; i<N; i++)
            for(int j=0; j<M; j++)
            {
                if(Map[i][j]=='A')
                {
                    card[0]++;
                    mat[i][j]=0;
                }
                else if(Map[i][j]=='B')
                {
                    card[1]++;
                    mat[i][j]=1;
                }
                else if(Map[i][j]=='C')
                {
                    card[2]++;
                    mat[i][j]=2;
                }
                else if(Map[i][j]=='D')
                {
                    card[3]++;
                    mat[i][j]=3;
                }
                else mat[i][j]=-1;
            }
        for(int i=0; i<4; i++)
        {
            count+=card[i];
            if(card[i]%2) flag=0;
        }
        if(!flag) printf("no\n");
        else
        {
            flag=0;
            dfs(count);
            if(flag) printf("yes\n");
            else printf("no\n");
        }
    }
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值