题目的意思就是给出几块碎片,碎片的四个边,可能是凹凸或者平的,F 平的 I 凹的,O凸的,要拼成 m × n的矩形。
那么第一排上面那个面一定要平,第一列左面的面要平,最后一列右面的面,最后一排下面的面要平。
首先剪枝,如果 F 数量不等于 2 × (m + n)也就不能构成矩形的边;
I O数量不相等的话,也不能全都对上;
还有就是如果某一块拼图不能放在这个位置,那和它一样的就不用试了;(由超时变A )
剩下就是回溯,能放进去就放进去。
AC代码:
#include <stdio.h>
#include<iostream>
#include<string>
#include <string.h>
#include <algorithm>
using namespace std;
const int N = 10;
int cmp(const void *a, const void *b) {
return strcmp((char*)a + 1 , (char*)b + 1); //按第二三四个字母排序。
}
int n, m;
char part[N * N][5];
char pos[N][N][5]; //记录在某一行某一列某个朝向的状态,用于判断下一个是否可以拼进去。
int vis[N * N];
int f, in, o;
int ok;
int yes(int s, int x, int y) {
if (part[s][0] == 'F' && x != 1 || part[s][1] == 'F' && y != m || part[s][2] == 'F' && x != n || part[s][3] == 'F' && y != 1)
return 0;
if ((part[s][0] == 'F' && pos[x - 1][y][2] != 'F') || (part[s][3] == 'F' && pos[x][y - 1][1] != 'F'))
return 0;
if ((part[s][0] == 'I' && pos[x - 1][y][2] != 'O') || (part[s][3] == 'I' && pos[x][y - 1][1] != 'O'))
return 0;
if ((part[s][0] == 'O' && pos[x - 1][y][2] != 'I') || (part[s][3] == 'O' && pos[x][y - 1][1] != 'I'))
return 0;
return 1;
}
void dfs(int x, int y) {
if (x > n) {
ok = 1;
return;
}
if (y > m) {
dfs(x + 1, 1);
return;
}
char temp[5] = {"asdf"};
for (int i = 0; i < n * m; i ++) {
if (!vis[i] && yes(i, x, y) && strcmp(temp,part[i])) {
strcpy (temp , part[i]);
strcpy ( pos[x][y] , part[i]);
for (int j = 0 ; j < 4 ;j++) {
pos[x][y][j] = part[i][j];
}
vis[i] = 1;
dfs(x, y + 1);
if(ok) return;
vis[i] = 0;
}
}
memset(pos[x][y], 0, sizeof(pos[x][y]));
}
int main() {
while (scanf("%d%d",&n,&m) && n + m) {
getchar();
ok = 0;
in = 0;
o = 0;
f = 0;
memset(pos, 0 , sizeof(pos));
memset(vis, 0, sizeof(vis));
for (int i = 1; i <= m; i ++) {
pos[0][i][2] = 'F';
}
for (int i = 1; i <= n; i ++) {
pos[i][0][1] = 'F';
}
for (int i = 0; i < n * m; i ++) {
gets( part[i] );
for (int j = 0; j < 4; j ++) {
if (part[i][j] == 'F') f++;
if (part[i][j] == 'I') in++;
if (part[i][j] == 'O') o++;
}
}
if (f != 2 * (n + m)) {
printf("NO\n");
continue;
}
if (in != o) {
printf("NO\n");
continue;
}
qsort(part, n * m, sizeof(part[0]), cmp);
cout <<endl;
for (int i = 0 ; i < n * m ;i++) {
puts( part[i]);
}
dfs(1, 1);
if (ok)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}