uva 11464 Even Parity(逐层递推)

uva 11464 Even Parity

We have a grid of size N x N. Each cell of the grid initially contains a zero(0) or a one(1).

The parity of a cell is the number of 1s surrounding that cell. A cell is surrounded by at most 4 cells (top, bottom, left, right).

Suppose we have a grid of size 4 x 4:

1 0 1 0
The parity of each cell would be

1 3 1 2
1 1 1 1 2 3 3 1
0 1 0 0 2 1 2 1
0 0 0 0 0 1 0 0

For this problem, you have to change some of the 0s to 1s so that the parity of every cell becomes even. We are interested in the minimum number of transformations of 0 to 1 that is needed to achieve the desired requirement.

Input

The first line of input is an integer T (T<30) that indicates the number of test cases. Each case starts with a positive integer N(1≤N≤15). Each of the next N lines contain N integers (0/1) each. The integers are separated by a single space character.

Output

For each case, output the case number followed by the minimum number of transformations required. If it’s impossible to achieve the desired result, then output -1 instead.

Sample Input

3

3

0 0 0

0 0 0

0 0 0

3

0 0 0

1 0 0

0 0 0

3

1 1 1

1 1 1

0 0 0

Output for Sample Input

Case 1: 0

Case 2: 3

Case 3: -1

题目大意:给你一个 n * n 的 01 矩阵,现在你的任务是将这个矩阵中尽量少的 0 转化为 1 ,使得每个数的上下左右四个相邻的数加起来是偶数。求最少的转化个数。

解题思路(转):

首先,n 的规模并不大,最大只有15。但是完全枚举整个矩阵显然是不可能的(2225 ≈ 5 * 1067)。但是我们可以枚举第一行,然后用第一行来算出后面的所有行。

但是,怎么算呢?

先来说下算法。对于每一行,我们通过他上面的两行来决定他的值。如果上面两行得到值为奇数,那么这一行就赋值为 1 ,否则赋值为 0 。 然后与原始矩阵比较,如果是由 1 变 0 那么这种情况是不允许的,于是继续枚举第一行,重新计算后面的。如果是由 0  变 1(或不变) 那么保存下来。最后在计算所有的格子之后,遍历一下就能统计转化数。然后取最小值就可以了。

下面用题目中给的第二组数据来演示一下如何通过上一行来计算下一行。

问题                                        正解

0 0 0                 ==>              0 1 0

1 0 0                 ==>              1 0 1

0 0 0                 ==>              0 1 0

来举例说明。首先我们通过枚举第一行可以达到以下情况

0 1 0
     
     

如下表我们开始通过第一行来计算第二行,对于 x 所在的这一格来说,把这一格当做他上面一格的下面相邻的格子进行计算,于是对于第一行第一列来说,他上下左右相加起来为 1 + x,因为要保证是偶数,所以 x = 1。接着与原矩阵进行比较,是符合题目要求的转化(不变)。保留,继续计算下一个。

0 1 0
x    
     

如下表开始计算第二行第二列,按照上面的方法,计算得出 0 + 0 + x 要为偶数,所以 x = 0。与原数组比较依旧是符合题目要求的。

0 1 0
1 x  
     

如下表计算第二行第三列,同上,得出 1 + x 要为偶数,所以 x  = 1。与原矩阵比较,发现是符合要求的转化(0 变 1)继续。

0 1 0
1 0 x
     

这样第二行就得出来了,是下面这种情况:

0 1 0
1 0 1
     

按照上述方法,可以计算出第三行,来完成这个例子的答案:

0 1 0
1 0 1
0 1 0

最后在说一下枚举第一行的 2 种方法,第一个种自然是直接深度优先搜索(DP)直接进行枚举。第二种可以利用位运算进行枚举。因为整数在内存中是用二进制存储的。只要让 s 从 0 开始一直加到 2n-1 – 1 这么大就可以枚举所有的情况。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#define INF 1 << 30
using namespace std;
int A[20][20], B[20][20];
int check(int n, int s) {
	memset(B, 0, sizeof(B));
	for (int i = 0; i < n; i++) {
		if (s & (1 << i)) {
			B[0][i] = 1;
		}
		else if (A[0][i] == 1) return INF;
	}
	for (int i = 1; i < n; i++) {
		for (int j = 0; j < n; j++) {
			int sum = 0;
			if (i > 1) sum += B[i - 2][j];
			if (j > 0) sum += B[i - 1][j - 1];
			if (j < n - 1) sum += B[i - 1][j + 1];
			if (sum % 2) B[i][j] = 1;
			if (B[i][j] == 0 && A[i][j] == 1) return INF;
		}
	}
	int cnt = 0;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			if (A[i][j] != B[i][j]) cnt++;
		}
	}
	return cnt;
}
int main() {
	int T, cnt = 1;
	scanf("%d", &T);
	while (T--) {
		int n;
		scanf("%d", &n);
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				scanf("%d", &A[i][j]);
			}
		}
		int ans = INF;
		for (int i = 0; i < (1 << n); i++) {
			ans = min(ans, check(n, i));
		}
		if (ans == INF) ans = -1;
		printf("Case %d: %d\n", cnt++, ans);
	}
	return 0;
}
时间: 2024-08-28 09:55:15

uva 11464 Even Parity(逐层递推)的相关文章

枚举 UVA 11464 Even Parity

题目传送门 1 /* 2 题意:求最少改变多少个0成1,使得每一个元素四周的和为偶数 3 枚举:枚举第一行的所有可能(1<<n),下一行完全能够由上一行递推出来,b数组保存该位置需要填什么 4 最后检查不同的数量,取最小值 5 */ 6 #include <cstdio> 7 #include <algorithm> 8 #include <cstring> 9 using namespace std; 10 11 const int MAXN = 20;

UVA - 10304Optimal Binary Search Tree(递推)

题目:UVA - 10304Optimal Binary Search Tree(递推) 题目大意:给出一组数,e1 < e2 < ... < en,现在要求将这些数组成一棵二叉搜索树,并且使得sum (ei * cost(ei))最小.cost(ei)表示ei到到根节点之间有多少条边. 解题思路:首先二叉搜索树要满足左节点小于根节点,右节点大于根节点.因此对于e1 < e2 < ... < en这样一组数,我们只要枚举根节点的位置ek,将这个序列分成左右子树两部分(e

UVA 11077 - Find the Permutations(递推)

UVA 11077 - Find the Permutations 题目链接 题意:给定n,k求出有多少个包含元素[1-n]的序列,交换k次能得到一个[1,2,3...n]的序列 思路:递推dp[i][j]表示i个元素需要j次,那么在新加一个元素的时候,添在最后面次数不变,其余位置都是次数+1,这是可以证明的,原序列中有几个循环,需要的次数就是所有循环长度-1的和,那么对于新加一个元素,加在最后就和自己形成一个循环,次数不变,其余位置都会加入其他循环中,次数+1,因此递推式为dp(i,j)=dp

UVA 474 - Heads / Tails Probability(递推)

UVA 474 - Heads / Tails Probability 题目链接 题意:给定n,求出2?n的科学计数法 思路:水水的,n最多到100w,那么先递推预处理出答案,然后输出即可 代码: #include <cstdio> #include <cstring> const int N = 1000001; const double eps = 1e-9; int n; struct Ans { double a; int b; } ans[N]; void build()

UVA - 10558A Brief Gerrymander(递推)

题目大意:UVA - 10558A Brief Gerrymander(递推) 题目大意:给定一个100 * 100 的矩形,现在要求将这个区域划分,竖着的线已经给你划分好了,现在要求你在这个区域内再添加A个横着的线,1 100 这两条是一定要的,问怎样选择横着的线,能够使得选举区间最多.选举区间的条件:内部没有横竖线,并且有一个点在区间内部.注意:边界上的点也是算在内的,但是要防止重复计算到选区内. 解题思路:这题题意都不是那么好理解了,然后写起来复杂度也是很大的.参考了别人的题解:首先:dp

UVA 11464 Even Parity(枚举递推)

11464 - Even Parity Time limit: 3.000 seconds We have a grid of size N x N. Each cell of the grid initially contains a zero(0) or a one(1). The parity of a cell is the number of 1s surrounding that cell. A cell is surrounded by at most 4 cells (top,

UVA - 11401 - Triangle Counting (递推!)

UVA - 11401 Triangle Counting Time Limit: 1000MS Memory Limit: Unknown 64bit IO Format: %lld & %llu Submit Status Description Problem G Triangle Counting Input: Standard Input Output: Standard Output You are given n rods of length 1, 2-, n. You have

UVA 11077 Find the Permutations 递推置换

                           Find the Permutations Sorting is one of the most used operations in real life, where Computer Science comes into act. It iswell-known that the lower bound of swap based sorting is nlog(n). It means that the best possiblesor

UVA 557 Burger 排列组合递推

When Mr. and Mrs. Clinton's twin sons Ben and Bill had their tenth birthday, the party was held at the McDonald's restaurant at South Broadway 202, New York. There were 20 kids at the party, including Ben and Bill. Ronald McDonald had made 10 hamburg