思路分析
暴力枚举?
我们可以枚举每个数字变或不变,最后判断整个矩阵是否满足条件。但是,这样做最多需要枚举 \(2^{255}≈5\times10^{67}\) 中情况,是一定会超时的。
大眼观察
注意到 \(n\le15\),第一行只有不超过 \(2^{15}=32768\) 种可能,所以第一行的情况是可以枚举的。接下来,根据第一行可以计算出第二行,根据第二行又能计算出第三行,以此类推,总时间复杂度即可降为 \(\mathcal O(2^n\times n^2)\)。
程序实现
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 20;
const int INF = INT_MAX;
int T, n, A[MAXN][MAXN], B[MAXN][MAXN];
int check(int s) { // 检查+扩展
memset(B, 0, sizeof(B));
for (int c = 0; c < n; c++) {
if (s & (1 << c)) B[0][c] = 1;
else if (A[0][c] == 1) return INF;
}
for (int r = 1; r < n; r++)
for (int c = 0; c < n; c++) {
int sum = 0;
if (r > 1) sum += B[r - 2][c];
if (c > 0) sum += B[r - 1][c - 1];
if (c < n - 1) sum += B[r - 1][c + 1];
B[r][c] = sum % 2;
if (A[r][c] == 1 && B[r][c] == 0) return INF;
}
int cnt = 0;
for (int r = 0; r < n; r++)
for (int c = 0; c < n; c++)
if (A[r][c] != B[r][c])
cnt++;
return cnt;
}
int main() {
cin >> T;
for (int cnt = 1; cnt <= T; cnt++) {
cin >> n;
for (int r = 0; r < n; r++)
for (int c = 0; c < n; c++)
cin >> A[r][c];
int ans = INF;
for (int s = 0; s < (1 << n); s++)
ans = min(ans, check(s));
if (ans == INF) ans = -1;
printf("Case %d: %d\n", cnt, ans);
}
return 0;
}
标签:cnt,int,题解,sum,UVA11464,枚举,MAXN,INF
From: https://www.cnblogs.com/IShallReturn/p/UVA11464-ti-jie.html