uva11464(遞推關係)

/*
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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章