您的位置:首页 > 其它

UVa --- 10464 Even Parity 偶数矩阵 【状态压缩 + 暴力枚举 + 思维】

2017-08-16 18:35 405 查看
传送门

//题意: 给你一个01矩阵, 问最少操作几次可以使得这个矩阵的任意一个元素的上下左右元素加起来是偶数. 操作是指可以将这个矩阵中的0变成1. 但是1不能变成0.

//思路: 由于n最大只有15, 所以我们可以考虑用二进制状压枚举出第一行的状态, 然后依次判断下面的状态, 最后得出的那个矩阵和原先的矩阵比较一下, 看有进行了多少次操作. 取最小的那次即可, 如果不能继续走下去了, 记得及时退出. 还要注意是一个元素的上下左右之和为偶数, 所以影响当前位是0还是1的是它的左上角和右上角和它上面二行的那三个元素(如果有的话). 所以判断是注意下写法.

//因为一个n最大才15,又只有01, 所以用15个字节就可以存下. 那么我就用的一个int位来存的.

AC Code

/** @Cain*/
const int maxn=15+5;
int mapp[maxn];
int tmp[maxn];
int n;
//先写好二进制位操作需要的操作函数.
int Getbit(int c,int i)
{//取数字c的第i个bit.
return (c >> i) & 1;
}

void Setbit(int & c,int i,int v)
{//把c的第i位设置成v.
if(v ) c |= (1 << i);
else c &= ~(1 << i);
}

void Flipbit(int & c ,int i)
{ //把c的第i位翻转.(1 翻为0 , 0 翻为 1).
c ^= (1 << i) ;
}

int cal(int k)
{
Fill(tmp,0);
for(int i=0;i<n;i++){
if(Getbit(k,i)) Setbit(tmp[0],i,1);
else if(Getbit(mapp[0],i)) return inf;   //1不能变成0.
}
for(int i=1;i<n;i++){
for(int j=0;j<n;j++){
int sum = 0; //这个元素的位置对应的上一行的位置的上,左,右3个元素的和.
if(j>0) sum += Getbit(tmp[i-1],j-1);  //好好理解题意和思维啊!!!
if(j<n-1) sum += Getbit(tmp[i-1],j+1);
if(i>1) sum += Getbit(tmp[i-2],j);
//如果不懂这三句话的意思,请再仔细看看题!
if(sum&1) Setbit(tmp[i],j,1);
else if(Getbit(mapp[i],j))  return inf;  //1不能变成0.
}
}
int cnt = 0;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(Getbit(mapp[i],j) != Getbit(tmp[i],j)) cnt++;
}
}
return cnt;
}
void solve()
{
scanf("%d",&n);
Fill(mapp,0); Fill(tmp,0);
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
int k; scanf("%d",&k);
Setbit(mapp[i],j,k);
}
}
int res = inf;
bool flag = false;
for(int k=0;k<(1<<n);k++){
res = min(res,cal(k));
}
printf("Case %d: ",cas++);
printf("%d\n",res==inf?-1:res);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: