poj 2308 Dearboy's Puzzle 连连看

本文探讨了游戏开发中的大数据应用,包括游戏性能优化、玩家行为分析和数据驱动的游戏设计,展示了如何将大数据技术融入游戏开发流程,提升游戏体验和商业价值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Dearboy's Puzzle
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 1258 Accepted: 223

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

Source

POJ Monthly,Wang Yijie


通过这个题,加深了对dfs和bfs的认识 ,dfs的特点在于回溯,不一定只限于走迷宫、选或不选、选下一个,

其结束的方式根据题目的不同有所变化,稍微做出变化可以应对不同的情况。

此题先用dfs,然后在dfs中再用dfs或bfs,

先用dfs是在整张图上试,看看消掉哪些对会怎样,具体的实现方法是先找到一个还没被消掉的点,然后从这个点出发,dfs或bfs找到与之成对的点。然后消掉他们,不断尝试,不断回溯,找到即可退出dfs。

底下有个重要的剪枝:

即图中某一部分出现底下这种情况且A、B都只剩下两个,最终不能消掉。

AB
BA



#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<climits>
#include<queue>
#include<vector>
#include<map>
#include<sstream>
#include<set>
#include<stack>
#include<utility>
//#pragma comment(linker, "/STACK:102400000,102400000")
#define PI 3.1415926535897932384626
#define eps 1e-10
#define sqr(x) ((x)*(x))
#define FOR0(i,n)  for(int i=0 ;i<(n) ;i++)
#define FOR1(i,n)  for(int i=1 ;i<=(n) ;i++)
#define FORD(i,n)  for(int i=(n) ;i>=0 ;i--)
#define  lson   num<<1,le,mid
#define rson    num<<1|1,mid+1,ri
#define MID   int mid=(le+ri)>>1
#define zero(x)((x>0? x:-x)<1e-15)

using namespace std;
const int INF =0x3f3f3f3f;
const int maxn= 10   ;
const int maxm= 10   ;
//const int INF=    ;
//typedef long long ll;
//ifstream fin("input.txt");
//ofstream fout("output.txt");
//fin.close();
//fout.close();
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
int  a[maxn+4][maxm+4];
   bool vis[maxn+2][maxm+2];
int num[6];
bool ok;
int n,m;
int dir[4][2]={  {-1,0},{+1,0},{0,-1},{0,+1} };
struct Node
{
    int y,x;
    int turn,dir;
    Node(){}
    Node(  int yy,int xx,int tur,int d ):y(yy),x(xx),turn(tur),dir(d) {}
    //dir代表方向,turn代表转弯次数

}   ;


bool in(Node &c)
{
    return 1<=c.y&&c.y<=n&&1<=c.x&&c.x<=m;
}
bool in(int &y,int &x)
{
    return 1<=y&&y<=n&&1<=x&&x<=m;
}
bool in(int y,int x)
{
    return 1<=y&&y<=n&&1<=x&&x<=m;
}
void bfs(int y,int x,int prin,int s[42][2],int& cct)
{
    queue<Node> q;


    Node st( y,x,0  ,-1);
    q.push(st);
     memset(vis,0,sizeof vis);
    vis[y][x]=1;
    while(!q.empty())
    {

        Node st=q.front();q.pop();

        for(int i=0;i<4;i++)
        {
            int ty=st.y+dir[i][0];
            int tx=st.x+dir[i][1];
            Node now(ty,tx,st.turn,i);
            if(!in(now)  || vis[ty][tx] )  continue;
            if(a[ty][tx]!=prin &&a[ty][tx]!=0 )  continue;

            if(i!=st.dir&& st.dir!=-1    )      now.turn+=1;

            if(now.turn>2)  continue;


              vis[ty][tx]=1;
            if(a[ty][tx]==prin)
                {
                      s[cct][0]=ty;
                     s[cct++][1]=tx;
                   continue;
                }
            q.push(now  );
        }
    }
}

bool cant()
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {

            if(!in( i+1,j+1)  )  continue;
            if( !a[i][j]  ||!a[i][j+1]  )  continue;
            if(a[i][j]==a[i+1][j+1]  &&  a[i][j+1]==a[i+1][j]   &&    num[a[i][j]]==2&&   num[a[i][j+1]]==2)
            return true;

        }
    }
    return false;
}
void dfs(int cnt)
{
    if(ok)  return;
   if(cnt==0)    {ok=1;return;}
     if(cant())  return;   //这个剪枝很重要
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
             if(ok)  return;
            if(!a[i][j])  continue;
            int s[42][2];int cct=0;
            int stcolor=a[i][j];
            bfs(  i,j, stcolor,  s, cct     );
            a[i][j]=0;
              num[ stcolor ]-=2;
            for(int k=0;k<cct;k++)
            {
                int y=s[k][0];
                int x=s[k][1];
                int nowcolor=a[y][x];
                a[y][x]=0;
//                if(cnt==2)   {ok=1;return;}
                dfs(cnt-2);
                a[y][x]=nowcolor;
            }
             num[stcolor]+=2;
            a[i][j]=stcolor;

        }
    }
}

int main()
{
    while(~scanf("%d%d",&n,&m)&&(n||m))
    {
        char c;
        int cnt=0;
        memset(num,0,sizeof num);
        FOR1(i,n)
        FOR1(j,m)
        {
            scanf(" %c",&c);
            if(c=='*')     num[0]++,a[i][j]=0;
            else if(c=='A')  num[1]++,a[i][j]=1,cnt++;
            else if(c=='B')  num[2]++,a[i][j]=2,cnt++;
            else if(c=='C')  num[3]++,a[i][j]=3,cnt++;
            else               num[4]++,a[i][j]=4,cnt++;
        }

        if( num[1]%2 ||num[2]%2 ||num[3]%2 ||num[4]%2 )
        {
            puts("no");continue;
        }
        ok=0;
        dfs(cnt);
      puts(ok?"yes":"no") ;
    }


    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值