题目大意: 给出N*M的矩阵,有N*M个拼图板,问能否把N*M的矩阵填满
解题思路:剪枝+回溯
1.F的数量要是2*(M+N),I和O的数量要想等
2.同层递归的话,相同的就跳过
3.第一行的up要为F,最后一行的bottom要为F,第一列的left要为F,最后一列的right要为F
4.判断条件,当前这块的left和左边的right相加的和%3要为0,当前这块的UP和上面的bottom的和%3也要为0(F的值为0,I的值为,0的值为2)
#include<cstdio>
#include<cstdlib>
#include<cstring>
struct puzzle{
int top;
int right;
int bottom;
int left;
}p[100];
int row,col;
int co,cf,ci;
int flag;
int vis[100];
int rec[100][100];
int value[100];
int change(char c) {
if(c == 'F') {
cf++;
return 0;
}
if(c == 'O') {
co++;
return 1;
}
if(c == 'I') {
ci++;
return 2;
}
}
void handle(char str[6],int i) {
p[i].top = change(str[0]);
p[i].right = change(str[1]);
p[i].bottom = change(str[2]);
p[i].left = change(str[3]);
}
int hash(int i) {
int temp = p[i].top + p[i].right * 3 + p[i].bottom * 9 + p[i].left * 27;
return temp;
}
void dfs(int r, int c) {
if(flag )
return ;
if(r > row) {
flag = 1;
return ;
}
int map[100];
memset(map,0,sizeof(map));
for(int i = 1 ; i <= row * col; i++) {
if(r == 1 && p[i].top != 0)
continue;
if(c == 1 && p[i].left != 0)
continue;
if(r == row && p[i].bottom != 0)
continue;
if(c == col && p[i].right != 0)
continue;
if(vis[i])
continue;
if(map[value[i]])
continue;
if( !( (p[i].left + p[rec[r][c-1]].right) % 3) && !( (p[i].top + p[rec[r-1][c]].bottom) %3)) {
rec[r][c] = i;
vis[i] = 1;
if(c == col)
dfs(r+1,1);
else
dfs(r,c+1);
if(flag)
return ;
vis[i] = 0;
map[value[i]] = 1;
}
}
}
void init() {
memset(rec,0,sizeof(rec));
memset(vis,0,sizeof(vis));
flag = 0;
cf = ci = co = 0;
p[0].top = p[0].left = p[0].right = p[0].bottom = 0;
}
int main() {
while(scanf("%d%d\n",&row,&col) != EOF && row+col) {
char temp[6];
init();
for(int i = 1; i <= row*col; i++) {
scanf("%s",temp);
handle(temp,i);
}
if(cf == 2*(row+col) && ci == co) {
for(int i = 1; i <= row*col; i++)
value[i] = hash(i);
dfs(1,1);
}
if(flag)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}