UVa 11464-Even Parity 偶数矩阵-bitmask+暴力

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=24665

题意:

给你一个 n * n 的 01 矩阵,现在你的任务是将这个矩阵中尽量少的 0 转化为 1 ,使得每个数的上下左右四个相邻的数(如果存在)加起来是偶数。求最少的转化个数。n<=15


n规模很小...直接暴力枚举整个矩阵2^(15*15)显然不科学....

可以发现只要第一行确定了,就能推出第二行...再从第二行推出第三行..

也就是只要暴力枚举第1行就好了  复杂度O(2^n)  每种情况对应要枚举一个矩阵,所以总复杂度O(2^n *  n*n)


#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;
int ori[16][16];
int tm[16][16];
const int inf=2147483647;
int n;
void copy_( )
{
	for (int i=2;i<=n;i++) 
		for (int j=1;j<=n;j++) 
			tm[i][j]=ori[i][j]; 
}
int ok(int i,int j)
{
	int sum=0;
	if (i+1<=n)			sum+= tm[i+1][j];
	if (i-1>=1)			sum+= tm[i-1][j];
	if (j+1<=n)			sum+= tm[i][j+1];
	if (j-1>=1)			sum+= tm[i][j-1];
	if (sum%2) return 0;
	else
		return 1;
}
int min(int a,int b)
{return a<b?a:b;}
int main()
{  
	int t;
	cin>>t;
	int cnt=1;
	while(t--)
	{
		int minn=inf;
		int i,j,k;
		scanf("%d",&n);
		for (i=1;i<=n;i++)
		{
			for (j=1;j<=n;j++)
				scanf("%d",&ori[i][j]);
		} 
		
		int cun=pow(2.0,n);
		for (i=0;i<cun;i++)
		{
			int ans=0;
			copy_();//copy ori[] to tm[]
			int tmp=i;
			int cun=0;
			for (j=1;j<=n;j++)
			{
				if (ori[1][j]==1) continue;		//only transfrom 0 to 1;
				tm[1][j]=tmp&1;
				if (ori[1][j]==0&&tm[1][j]==1) cun++;  //count the num of changed “1” from “0”
				tmp>>=1;
			}
			for (j=2;j<=n;j++)
			{
				for (k=1;k<=n;k++)
				{
					if (!ok(j-1,k))  //if (the sum%2!=0)
					{
						if (tm[j][k]==1)	//cannot change
						{
							ans=inf;
							break;
						}
						ans++;					//can change
						tm[j][k]=!tm[j][k];
					}
				}
				if (ans==inf) break;
			}
			if (ans==inf) continue;
			minn=min(minn,ans+cun);
		}
		if (minn==inf)
			minn=-1;
		printf("Case %d: %d\n",cnt++,minn); 
		
		
	}
	
	
	return 0;
	
}

 


你可能感兴趣的:(UVa 11464-Even Parity 偶数矩阵-bitmask+暴力)