toj 4317 多连块拼图
时间限制(普通/Java):1000MS/3000MS 内存限制:65536KByte
总提交: 40 测试通过:21
描述
多连块是指由多个等大正方形边与边连接而成的平面连通图形。 ———— 维基百科
给一个大多连块和小多连块,你的任务是判断大多连块是否可以由两个这样的小多连块拼成。小多连块只能平移,不能旋转或者翻转。两个小多连块不得重叠。左下图是一个合法的拼法,但右边两幅图都非法。中间那幅图的问题在于其中一个小多连块旋转了,而右图更离谱:拼在一起的那两个多连块根本就不是那个给定的小多连块(给定的小多连块画在右下方)。
输入
输入最多包含 20 组测试数据。每组数据第一行为两个整数 n 和 m(1<=m<=n<=10)。以下 n 行描述大多连块,其中每行恰好包含 n 个字符或者.,其中表示属于多连块,.表示不属于。以下 m 行为小多连块,格式同大多连块。输入保证是合法的多连块(注意,多连块至少包含一个正方形)。输入结束标志为 n=m=0。
输出
对于每组测试数据,如果可以拼成,输出 1,否则输出 0。
样例输入
4 3
.**.
.**.
….
**.
.**
…
3 3
.
*..
*..
**.
4 2
….
….
….
*.
*.
0 0
样例输出
1
0
0
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
char small[10][10], big[10][10];
int x1, y1, x2, y2, n, m;
/**
获得大多连块的第一个‘*’位置
*/
void get_big() {
bool flag = true;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (big[i][j] == '*') {
x1 = i;
y1 = j;
flag = false;
break;
}
}
if (!flag) break;
}
}
/**
获得小多连块的第一个‘*’位置
*/
void get_small() {
bool flag = true;
//m为小多连块的宽度
for (int i = 0; i < m; i++) {
for (int j = 0; j < m; j++) {
if (small[i][j] == '*') {
x2 = i;
y2 = j;
flag = false;
break;
}
}
if (!flag) break;
}
}
/**
判断是否全部匹配
*/
bool judge() {
//n为大多连块的宽度
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (big[i][j] == '*')
return false;
return true;
}
/**
匹配过程
*/
int sovle() {
get_small();
while (!judge()) {
//获取大多连块的第一个‘*’的位置
get_big();
//m是小多连块的宽度
for (int i = 0; i < m; i++)
for (int j = 0; j < m; j++) {
if (small[i][j] == '*') {
//关键就是这里,用小连块的位置去匹配大连块的位置
if (big[x1 + i - x2][y1 + j - y2] == '*')
big[x1 + i - x2][y1 + j - y2] = '.';
else//小连块中出现中出现‘*’而大连块中未出现则一定会消除不干净
return 0;
}
}
}
return 1;
}
int main() {
int i, j;
while (scanf("%d%d", &n, &m) && n && m) {
//将大多连块录入二维数组中
for (i = 0; i < n; i++)
scanf("%s", big[i]);
//将小多连块录入二维数组中
for (j = 0; j < m; j++)
scanf("%s", small[j]);
//输出结果
printf("%d\n", sovle());
}
return 0;
}