Uva--519(回溯,剪枝)
2014-07-20 21:00:37
Puzzle (II) |
Little Barborka has just started to learn how to solve a picture puzzle. She has started with a small one containing 15 pieces. Her daddy tries to solve the puzzle too. To make it a little bit harder for himself, he has turned all puzzle pieces upside down so that he cannot see pictures on the pieces. Now he is looking for a solution of the puzzle. Normally the solution should exist but he is not sure whether Barborka has not replaced some pieces of the puzzle by pieces of another similar puzzle. Help him and write a program which reads a description of a set of puzzle pieces and decides whether it is possible to assembly the pieces into a rectangle with given side lengths or not.
Input
The input file consists of blocks of lines. Each block except the last describes one puzzle problem. In the first line of the block there are integers n and m, separated by one space. The integers n, m indicate the number of rows and columns in the puzzle respectively. The description of individual puzzle pieces is in the following lines of the block. Each piece is a rectangle 3 centimeters wide and 4 centimeters high with possible juts or cavities in the middle of its sides. For each side of a puzzle piece just one of the following possibilities is true (see picture):
- there is no jut or cavity on the side, i.e., the side is flat - such sides can be used only on edges of the final picture when assembling the puzzle,
- there is one jut in the middle of the side,
- there is one cavity in the middle of the side.
As is usual, two pieces can be placed side by side only if one has a jut and the other has a cavity on corresponding sides. We will denote the flat sides by F, the sides with juts by O and the sides with cavities by I. Each piece is described by four letters characterizing its top, right, bottom, and left side. To make the task easier the pieces can be used only as they are described i.e. they cannot be turned.
After each block there is an empty line. The last block consists of just one line containing 0 0, i.e. two zeros separated by one space.
Output
The output file contains the lines corresponding to the blocks in the input file. A line contains YES if the corresponding block in the input file describes a puzzle that can be correctly assembled. Otherwise it contains NO. There is no line in the output file corresponding to the last ``null'' block of the input file.
Sample Input
3 5 FOOF FOOI FOOI FOOI FFOI IOOF IOOI IOOI IOOI IFOI IOFF IOFI IOFI IOFI IFFI 0 0
Sample Output
YES
思路:几个关键点:
(1)内部的拼图块四边不能是平的(’F'),所以’F'的总数若不为2 × (n + m)就拼不成拼图。(剪枝)
(2)对所有拼图块进行一个排序,再加上在判断过程中:若前一个块和该块一样且前一个块不取,则该块也不取。(剪枝)
(3)注意边界:上下左右的边界要为‘F'
1 /************************************************************************* 2 > File Name: Uva519.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Sun 20 Jul 2014 03:59:19 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <iostream> 13 #include <algorithm> 14 #include <queue> 15 #include <stack> 16 #include <set> 17 #include <map> 18 using namespace std; 19 #define INF 0x3f3f3f3f 20 #define eps 1e-8 21 #define PI acos(-1.0) 22 typedef long long LL; 23 24 int sum,row,col,used[40],g[10][10]; 25 26 struct pie{ 27 char sh[5]; 28 //0 : top 29 //1 : right 30 //2 : bottom 31 //3 : left 32 }p[40]; 33 34 bool Check(int r,int c,int k){ 35 if(r == 0 && p[k].sh[2] != 'F') 36 return false; 37 else if(r == row - 1 && p[k].sh[0] != 'F') 38 return false; 39 if(c == 0 && p[k].sh[3] != 'F') 40 return false; 41 else if(c == col - 1 && p[k].sh[1] != 'F') 42 return false; 43 if(r > 0){ 44 if(p[g[r - 1][c]].sh[0] == 'F' && p[k].sh[2] != 'F') 45 return false; 46 if(p[g[r - 1][c]].sh[0] == 'O' && p[k].sh[2] != 'I') 47 return false; 48 if(p[g[r - 1][c]].sh[0] == 'I' && p[k].sh[2] != 'O') 49 return false; 50 } 51 if(c > 0){ 52 if(p[g[r][c - 1]].sh[1] == 'F' && p[k].sh[3] != 'F') 53 return false; 54 if(p[g[r][c - 1]].sh[1] == 'O' && p[k].sh[3] != 'I') 55 return false; 56 if(p[g[r][c - 1]].sh[1] == 'I' && p[k].sh[3] != 'O') 57 return false; 58 } 59 return true; 60 } 61 62 bool Dfs(int r,int c){ 63 int next_r = r,next_c = c; 64 if(c >= col - 1){ 65 next_c = 0; 66 ++next_r; 67 } 68 else ++next_c; 69 for(int i = 0; i < sum; ++i){ 70 if(used[i]) continue; 71 if(i > 0 && !used[i - 1] && strcmp(p[i - 1].sh,p[i].sh) == 0) continue; 72 if(Check(r,c,i)){ 73 if(r >= row - 1 && c >= col - 1) 74 return true; 75 g[r][c] = i; 76 used[i] = 1; 77 if(Dfs(next_r,next_c)) 78 return true; 79 used[i] = 0; 80 g[r][c] = 0; 81 } 82 } 83 return false; 84 } 85 86 void Init(){ 87 memset(p,0,sizeof(p)); 88 memset(g,-1,sizeof(g)); 89 memset(used,0,sizeof(used)); 90 } 91 92 bool cmp(pie a,pie b){ 93 return strcmp(a.sh,b.sh) < 0; 94 } 95 96 int main(){ 97 while(scanf("%d%d",&row,&col) == 2){ 98 if(!row && !col) 99 break; 100 Init(); 101 sum = row * col; 102 int fcnt = 0; 103 for(int i = 0; i < sum; ++i){ 104 scanf("%s",p[i].sh); 105 for(int j = 0; j < 4; ++j) if(p[i].sh[j] == 'F') 106 ++fcnt; 107 } 108 sort(p,p + sum,cmp); 109 if(fcnt == 2 * (row + col) && Dfs(0,0)) 110 printf("YES\n"); 111 else 112 printf("NO\n"); 113 } 114 return 0; 115 }