题目描述
有一个 N 行
N 列的表格,每个格子刚开始都是白色的(用数字0表示)。每轮染色是:
1、每次你选择表格中的任意一个长方形(正方形也可以认为是长方形),长方形的4条边必须是水平的或者竖直的。
2、然后给该长方形内部染成一种颜色,颜色用数字1至9表示。总共染色9轮,每轮只使用一种颜色,每种颜色只用一次,注意:同一个格子,后染的颜色会把该格子之前染的颜色覆盖掉。
例如:
第1轮染色(用颜色2)后是:
2220
2220
2220
0000
第2轮染色(颜色7)后是:
2220
2777
2777
0000
第3轮染色(用颜色3)后是:
2230
2737
2777
0000现在给出经过9轮染色之后的表格的各个格子的最终颜色,在最终你能看到的那些颜色当中(例如在上面例子中,最终你能看到的颜色是2,3,7),
有多少种颜色可能是第1轮染色过程中使用的颜色?
输入格式 1726.in
第一行,一个整数 N 。
1≤N≤10 。
接下来是 N 行N 列的表格,表示经过9轮染色之后,各个格子的最终颜色,每个格子的最终颜色是0至9。
输出格式 1726.out
一个整数。
输入样例 1726.in
4
2230
2737
2777
0000
输出样例 1726.out
1
样例说明
颜色3不可能是第一轮染色使用的颜色,颜色7不可能是第一轮染色使用的颜色,只有颜色2可能是第一轮染色使用的颜色。所以输出1。
可以看到,这题的数据范围非常小,完全可以直接用搜索做,枚举可能的颜色并判断即可。
判断这里有点小问题。直接判断某种颜色是否可能为第一种颜色是不容易写的,不妨换个角度考虑。其实可以采用排除法,对于某两种颜色,如果在一种颜色
i
的范围内出现了另一种颜色
为了方便,可以先预处理出每种颜色出现的位置范围。总的时间复杂度为
参考代码:
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn = 10 + 5;
int n;
char a[maxn][maxn];
int minx[maxn], maxx[maxn], miny[maxn], maxy[maxn];
bool f[maxn];
bool check(int n1, int n2) {
for (int i = minx[n1]; i <= maxx[n1]; i++)
for (int j = miny[n1]; j <= maxy[n1]; j++)
if (n2 + '0' == a[i][j]) return true;
//printf("%d %d\n", n1, n2);
return false;
}
int main(void) {
freopen("1726.in", "r", stdin);
freopen("1726.out", "w", stdout);
scanf("%d", &n);
memset(minx, 0x7f, sizeof minx); memset(miny, 0x7f, sizeof miny);
for (int i = 1; i <= n; i++) {
scanf("%s", a[i] + 1);
for (int j = 1; j <= n; j++) {
int num = a[i][j] - '0'; f[num] = true;
minx[num] = min(minx[num], i); maxx[num] = max(maxx[num], i);
miny[num] = min(miny[num], j); maxy[num] = max(maxy[num], j);
}
}
for (int i = 1; i < 10; i++)
if (maxx[i]) {
bool bo = true;
for (int j = 1; j < 10 && bo; j++)
if (i != j && maxx[j])
if (check(i, j)) f[j] = false;
}
int ans = 0;
for (int i = 1; i < 10; i++) if (f[i]) /*printf("%d ", i), */ans += f[i];
printf("%d\n", ans);
return 0;
}