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, 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       Output for 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
 

Case 1: 0           

Case 2: 3

Case 3: -1

题意:给出一个n*n的01矩阵(每个元素非0即1),选择尽量少的0变成1,使得每个元素的上下左右的元素纸盒均为偶数。如果无解,输出-1.

分析:最容易想到的方法是枚举每个数字“变”还是“不变”,最后判断整个矩阵是否满足条件。这样做最多需要枚举2^225种情况,难以承受。

注意到n只有15,每一行只有不超过2^15=32768种情况,所以可以枚举第一行的情况。接下来可以根据第一行计算出第二行,根据第二行计算出第三行……这样,总时间复杂度降为O(2^n * n^2)。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 20;
const int INF = 0x3fffffff;
int n, A[N][N], B[N][N];

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; //1不能变成0
    }
    for(int r = 1; r < n; r++) {
        for(int c = 0; c < n; c++) {
            int sum = 0; //元素B[r-1][c]的上、左、右3个元素之和
            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(B[r][c] == 0 && A[r][c] == 1) return INF; //1不能变成0
        }
    }
    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() {
    int T, cas = 0;
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        for(int r = 0; r < n; r++)
            for(int c = 0; c < n; c++)
                scanf("%d", &A[r][c]);
        int ans = INF;
        for(int i = 0; i < (1<<n); i++)
            ans = min(ans, check(i));
        if(ans == INF) ans = -1;
        printf("Case %d: %d\n", ++cas, ans);
    }
    return 0;
}
时间: 2024-11-04 09:09:43

UVA 11464 Even Parity(枚举递推)的相关文章

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). Su

枚举 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

HRBUST 1211 火车上的人数【数论解方程/模拟之枚举+递推】

火车从始发站(称为第1站)开出,在始发站上车的人数为a,然后到达第2站,在第2站有人上.下车,但上.下车的人数相同,因此在第2站开出时(即在到达第3站之前)车上的人数保持为a人.从第3站起(包括第3站)上.下车的人数有一定规律:上车的人数都是前两站上车人数之和,而下车人数等于上一站上车人数,一直到终点站的前一站(第n-1站),都满足此规律.现给出的条件是:共有N个车站,始发站上车的人数为a,最后一站下车的人数是m(全部下车).试问x站开出时车上的人数是多少?Input有多组测试数据.每组测试数据

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