poj 2308 Dearboy's Puzzle 连连看
2015-08-03 23:37
232 查看
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
Sample Output
Source
POJ Monthly,Wang Yijie
通过这个题,加深了对dfs和bfs的认识 ,dfs的特点在于回溯,不一定只限于走迷宫、选或不选、选下一个,
其结束的方式根据题目的不同有所变化,稍微做出变化可以应对不同的情况。
此题先用dfs,然后在dfs中再用dfs或bfs,
先用dfs是在整张图上试,看看消掉哪些对会怎样,具体的实现方法是先找到一个还没被消掉的点,然后从这个点出发,dfs或bfs找到与之成对的点。然后消掉他们,不断尝试,不断回溯,找到即可退出dfs。
底下有个重要的剪枝:
即图中某一部分出现底下这种情况且A、B都只剩下两个,最终不能消掉。
AB
BA
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 1258 | Accepted: 223 |
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; }
相关文章推荐
- 负数在计算机中的表示
- 密码管理器LastPass和KeePass对比评测
- 微信公众平台开发:进阶篇(在网页上添加分享到朋友圈、发送给好友、分享等按钮)
- 【树结构】CodeForces 396C
- uva 127
- MySQL学习笔记_如何选择合适的存储引擎
- eclipse导入到android studio的正确姿势
- ZOJ_3195_Design the city(LCA+tarjan)
- 犀牛——第7章数组 7.1 创建数组
- DataStructure-5-字符串
- Android之史上最强ListView优化方案
- iOS- 给App添加内购& 验证购买iOS8新特性
- 微信公众平台开发:进阶篇(Web App开发入门)
- bootstrap charisma 入门学习笔记
- SQL中Where与Having的区别 .
- hd1969 Pie
- Thrift 基础教程(二)编码篇
- 回调函数之感想
- js中的内部属性与delete操作符
- lucence.net+盘古分词