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.
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.
3 5 FOOF FOOI FOOI FOOI FFOI IOOF IOOI IOOI IOOI IFOI IOFF IOFI IOFI IOFI IFFI 0 0
YES
给你一堆方块,方块的边有的凹有的凸有的平,问能不能构成一个矩形。
明显的dfs+剪枝。
1.F(平的)数量要等于周长,因为中间必须要是凹凸衔接,所以OI数量也要想等。
2.当前位置放一块方块不行,那么相同方块就不需要试了,这个剪枝是很通用的。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> #include <string> using namespace std; int n, m, tot, f; int num[36], c[10][10]; string s[36], ss; void work(int sum) { if (sum > n*m) {f = 1; return;} if (f) return; int x = (sum - 1) / m + 1, y = (sum - 1) % m + 1; for (int i = 0; i < tot; i++) if (num[i]) { if (x == 1 && s[i][0] != 'F') continue; if (y == 1 && s[i][3] != 'F') continue; if (x > 1 && s[i][0] + s[c[x - 1][y]][2] != 'O' + 'I') continue; if (y > 1 && s[i][3] + s[c[x][y - 1]][1] != 'O' + 'I') continue; if (x < n&&s[i][2] == 'F') continue; if (y < m&&s[i][1] == 'F') continue; if (x == n&&s[i][2] != 'F') continue; if (y == m&&s[i][1] != 'F') continue; c[x][y] = i; num[i]--; work(sum + 1); if (f) return; num[i]++; } } int main() { while (cin >> n >> m, n, m) { tot = 0; memset(num, 0, sizeof(num)); int ff = 0, io = 0; for (int i = 0, j = 0; i < n*m; i++) { cin >> ss; for (j = 0; j < 4; j++) { if (ss[j] == 'O') io++; if (ss[j] == 'I') io--; if (ss[j] == 'F') ff++; } for (j = 0; j < tot;j++) if (ss == s[j]) { num[j]++; break; } if (j == tot) { s[tot] = ss; num[tot] = 1; tot++; } } f = 0; if (ff == n + m + n + m&&io == 0) work(1); if (f) cout << "YES" << endl; else cout << "NO" << endl; } return 0; }