/*
translation:
給出一個矩陣,每個數字要麼0要麼是1。可以將若干個0變換成1,問最少需要多少個這樣的變換才能使得矩陣變成
偶數矩陣。一個偶數矩陣裏面每一個數字的上下左右數字加起來的和都是偶數。
solution:
遞推
關鍵是找到遞推關係。因爲一行最多隻要15個數字,所以可以暴力枚舉出第一行的狀態。然後根據第一行的狀態其實就可以確定下一行
的狀態了。進而就可以推出整個矩陣的狀態了。不斷更新迭代,即可找到答案。
*/
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 15;
const int INF = 0x3f3f3f3f;
int grid[maxn + 5][maxn + 5], n;
bool check(int s, int row)
{
for(int col = 0; col < n; col++) {
if(grid[row][col] == 1 && !(s >> (n - 1 - col) & 1))
return false;
}
return true;
}
int count_bit(int s, int row)
{
int res = 0;
for(int col = 0; col < n; col++) {
if(grid[row][col] == 0 && s >> (n - 1 - col) & 1)
res++;
}
return res;
}
int get_bit(int s, int p)
{
if(p < 0 || p >= n) return 0;
if(s >> p & 1) return 1;
else return 0;
}
int generate_next(int last_s, int s)
{
int next_s = 0;
for(int i = 0; i < n; i++) {
if((get_bit(s, i+1) + get_bit(s, i-1) + get_bit(last_s, i)) & 1) {
next_s |= 1 << i;
}
}
return next_s;
}
int calculate(int s, int last_s)
{
int res = 0;
for(int i = 0; i < n; i++) {
if(!check(s, i)) return INF;
res += count_bit(s, i);
int next_s = generate_next(last_s, s);
last_s = s;
s = next_s;
}
return res;
}
int main()
{
//freopen("in.txt", "r", stdin);
int T, kase = 0;
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
scanf("%d", &grid[i][j]);
}
}
int status = 0;
for(int i = 0; i < n; i++)
if(grid[0][n-i-1]) status |= 1 << i;
int res = INF;
for(int s = status; s < 1 << n; s++) {
res = min(res, calculate(s, 0));
//printf("# = %d\n", calculate(s, 0));
}
if(res >= INF) res = -1;
printf("Case %d: %d\n", ++kase, res);
}
return 0;
}
uva11464(遞推關係)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.