UVA 11464-Even Parity(偶数矩阵-开关问题)

来源:互联网 发布:python rfm模型 编辑:程序博客网 时间:2024/06/05 02:13

11464 - Even Parity

Time limit: 3.000 seconds

We have a grid of size N × N. Each cell of the grid initially contains a zero(0) or a one(1). The parityof 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 × 4:


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

Input

The first line of input is an integer T (T < 30) that indicates the number of test cases. Each case startswith a positive integer N (1 ≤ N ≤ 15). Each of the next N lines contain N integers (0/1) each. Theintegers 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

Sample Output

Case 1: 0

Case 2: 3

Case 3: -1

题目意思:

有一个N*N的01矩阵,你的任务是把尽量少的0变成1,使得每个元素的上下左右的元素(若存在)均为偶数。

解题思路:

Note:0可以变成1,但是1不能变成0

N最大是15,我们只需要枚举第一行,每个数只能为0/1,所以最多2^15个,剩下的每一行都可以根据第一行来确定。

求解过程中用一个新的矩阵保存我们找到的解,与原矩阵相比较,计算出改变的元素个数。

枚举过程中:

①状态压缩

if(s & (1<<i)) m[0][i]=1;//判断该位是否为1
因为数最大范围是000~111共15种,所以可以分别对应枚举第一行元素值的所有情况。

按位与&运算(只有全1才为1)判断该位是否为1,如果是1,则新矩阵该位置1;如果原来的矩阵中该位为1,则无法求解,函数直接返回返回无解;

1不能变成0

 if(f[i][j]==1&&m[i][j]==0) return INF;//别忘了这句,1不能转换成0
注意特判这种无法转换的情况,无法继续求解,函数直接返回返回无解。

#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <bitset>#include <algorithm>using namespace std;#define INF 0x3f3f3f3f#define maxn 16int m[maxn][maxn],f[maxn][maxn];int n;int valid(int s){    memset(m,0,sizeof(m));    int cnt=0;    for(int i=0; i<n; ++i)    {        if(s & (1<<i)) m[0][i]=1;        else if(f[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+=m[i-2][j];            if(j>0)//左                sum+=m[i-1][j-1];            if(j+1<n)//右                sum+=m[i-1][j+1];            m[i][j]=sum%2;            if(f[i][j]==1&&m[i][j]==0) return INF;//别忘了这句,1不能转换成0        }    for(int i=0; i<n; ++i)        for(int j=0; j<n; ++j)            if(m[i][j]!=f[i][j]) ++cnt;    return cnt;}int main(){    int t,ca=0;    scanf("%d",&t);    while(t--)    {        int ans=INF;        scanf("%d",&n);        for(int i=0; i<n; ++i)            for(int j=0; j<n; ++j)                scanf("%d",&f[i][j]);        for(int i=0; i<(1<<n); ++i)            ans=min(ans,valid(i));        if(ans==INF) ans=-1;        printf("Case %d: %d\n",++ca,ans);    }    return 0;}/*330 0 00 0 00 0 030 0 01 0 00 0 031 1 11 1 10 0 0*/


0 0
原创粉丝点击