Dearboy's Puzzle (poj 2308 搜索 dfs+bfs)

原创 2015年07月06日 20:42:13



Language:
Dearboy's Puzzle
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 1202   Accepted: 208

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来确定消去哪一个格子(x,y),在dfs中进行bfs,看(x,y)周围有多少格子可以和(x,y)相消,找到之后再用dfs枚举与哪一个相消或者当前(x,y)不消。

注意一个剪枝,存在下面这种情况的肯定不符合题意:

*********

***AB***

***BA***

*********

另外,注意题意的消去方法,连线最多只转两个弯。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define maxn 1005
#define MAXN 2005
#define mod 1000000009
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define FRE(i,a,b)  for(i = a; i <= b; i++)
#define FREE(i,a,b) for(i = a; i >= b; i--)
#define FRL(i,a,b)  for(i = a; i < b; i++)
#define FRLL(i,a,b) for(i = a; i > b; i--)
#define mem(t, v)   memset ((t) , v, sizeof(t))
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf          printf
#define DBG         pf("Hi\n")
typedef long long ll;
using namespace std;

struct Node
{
    int x,y,turn,w,d; //turn是走到当前(x,y)处已经转了多少个弯,d是(x,y)是有上一步哪个方向来的
};

int dir[4][2]={1,0,0,1,0,-1,-1,0};
int mp[11][11],num[4];
int n,m;
char str[11];
bool flag;

bool isok(int x,int y)
{
    if (x>=0&&x<n&&y>=0&&y<m) return true;
    return false;
}

bool isOK()
{
    for (int i=0;i<n;i++)
    {
        for (int j=0;j<m;j++)
        {
            if (mp[i][j]!=-1&&mp[i][j+1]!=-1&&num[mp[i][j]]==num[mp[i][j+1]]&&num[mp[i][j]]==2)
            {
                if (mp[i][j]==mp[i+1][j+1]&&mp[i][j+1]==mp[i+1][j])
                    return true;
            }
        }
    }
    return false;
}

void bfs(int x,int y,int v,int s[25][2],int &nn)
{
    nn=0;
    queue<Node>Q;
    Node st,now;
    st.x=x; st.y=y; st.w=-1; st.turn=0; st.d=-1;
    bool vis[11][11];
    memset(vis,false,sizeof(vis));
    vis[x][y]=true;
    Q.push(st);
    while (!Q.empty())
    {
        st=Q.front();Q.pop();
        if (st.w==v)
        {
            s[nn][0]=st.x;      //记录下找到的可以相消的格子的坐标
            s[nn++][1]=st.y;
            continue;
        }
        for (int i=0;i<4;i++)
        {
            now.x=st.x+dir[i][0];
            now.y=st.y+dir[i][1];
            if (isok(now.x,now.y)&&!vis[now.x][now.y])
            {
                if (mp[now.x][now.y]!=-1&&mp[now.x][now.y]!=v) continue;
                if (st.d==i||st.d==-1)
                    now.turn=st.turn;
                else
                    now.turn=st.turn+1;
                if (now.turn<=2)
                {
                    now.w=mp[now.x][now.y];
                    now.d=i;
                    vis[now.x][now.y]=true;
                    Q.push(now);
                }
            }
        }
    }
}

void dfs(int cnt)
{
    if (flag) return ;
    if (cnt==0)
    {
        flag=true;
        return;
    }
    if (isOK()) return ;        //剪枝
    for (int i=0;i<n;i++)
    {
        for (int j=0;j<m;j++)
        {
            if (mp[i][j]!=-1)
            {
                int s[25][2];
                int sum;
                int v=mp[i][j];
                bfs(i,j,v,s,sum);
                num[v]-=2;
                mp[i][j]=-1;
                for (int k=0;k<sum;k++)
                {
                    int x=s[k][0];
                    int y=s[k][1];
                    mp[x][y]=-1;
                    dfs(cnt-2);
                    mp[x][y]=v;
                }
                num[v]+=2;
                mp[i][j]=v;
            }
        }
    }
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("C:/Users/asus1/Desktop/IN.txt","r",stdin);
#endif
    int i,j;
    while (scanf("%d%d",&n,&m))
    {
        if (n==0&&m==0) break;
        flag=false;
        mem(num,0);
        mem(mp,-1);
        int all=0;
        for (i=0;i<n;i++)
        {
            scanf("%s",str);
            for (j=0;j<m;j++)
            {
                if (str[j]=='*') mp[i][j]=-1;
                else if (str[j]=='A'){
                    num[0]++;
                    mp[i][j]=0;
                    all++;
                }
                else if (str[j]=='B')
                {
                    num[1]++;
                    mp[i][j]=1;
                    all++;
                }
                else if (str[j]=='C')
                {
                    num[2]++;
                    mp[i][j]=2;
                    all++;
                }
                else{
                    num[3]++;
                    mp[i][j]=3;
                    all++;
                }
            }
        }
        if (num[0]%2||num[1]%2||num[2]%2||num[3]%2) //存在奇数时肯定不合要求
        {
            pf("no\n");
            continue;
        }
        dfs(all);
        if (flag)
            pf("yes\n");
        else
            pf("no\n");
    }
    return 0;
}



Language:
Dearboy's Puzzle
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 1202   Accepted: 208

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)

深度优先搜索算法(Depth First Search),是搜索算法的一种。是沿着树的深度遍历树的节点,尽可能深的搜索树的分支。 当节点v的所有边都己被探寻过,搜索将回溯到发现节点v的那条边的起...
  • chlele0105
  • chlele0105
  • 2014年08月22日 17:21
  • 7802

<C/C++图>搜索算法:DFS与BFS

一,图的遍历基本理论 首先定义图的遍历(Traversing Graph):指从图中某一顶点出发访问图中其余顶点,且使每个顶点仅被访问一次。有两种常用的方法可用来搜索图:即深度优先搜索和广度优先搜...
  • EbowTang
  • EbowTang
  • 2015年03月14日 21:32
  • 3952

经典算法研究系列:四、教你通透彻底理解:BFS和DFS优先搜索算法

4、教你通透彻底理解:BFS和DFS优先搜索算法    作者:July  二零一一年一月一日 --------------------------------- 本人参考:算法导论...
  • dongchosenone
  • dongchosenone
  • 2014年09月28日 10:37
  • 1057

POJ2308 Dearboy's Puzzle(DFS+BFS)

连连看的小游戏(只有4种牌),判断是否能全部消除。思路非常简单但是要注意减枝。 外层的DFS指定一张牌来想办法消除它,内层的BFS以指定的这张牌为起点,向四周扩展找到能和它配对的牌。然后每一对能消除...
  • cqbzwja
  • cqbzwja
  • 2016年03月28日 14:54
  • 226

POJ2308连连看dfs+bfs+优化

DFS+BFS+MAP+剪枝 题意:       就是给你一个10*10的连连看状态,然后问你最后能不能全部消没? 思路:      首先要明确这是一个搜索题目,还有就是关键的一点就是连连...
  • u013761036
  • u013761036
  • 2015年02月06日 16:49
  • 521

POJ 2308 DFS+BFS

题目链接:http://poj.org/problem?id=2308 这题没什么坑,就是dfs+bfs,bfs搜索当前方块可以与哪个快消,dfs暴力枚举先消哪个对。 /*----------...
  • q437634645
  • q437634645
  • 2016年04月15日 23:07
  • 217

acm-ICPC 搜索算法DFS和BFS文件格式(ppt)经典算法“剪枝”等算法

  • 2009年09月11日 21:00
  • 535KB
  • 下载

搜索bfs,dfs

  • 2017年09月13日 10:48
  • 198KB
  • 下载

POJ 1573 Robot Motion【是搜索,就不要纠结是DFS还是BFS】

Robot Motion Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 12845   Accepted: 62...
  • hurmishine
  • hurmishine
  • 2016年08月08日 11:17
  • 1395

BFS广度优先搜索(5)(亦可以用DFS)--hdu1241(poj1562)(基础题)

Oil Deposits Limit:1000MS    Memory Limit:32768KB    64bit IO Format:%I64d & %I64u Description...
  • Acmer_Sly
  • Acmer_Sly
  • 2016年09月14日 00:23
  • 308
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Dearboy's Puzzle (poj 2308 搜索 dfs+bfs)
举报原因:
原因补充:

(最多只允许输入30个字)