UVA.11464 Even Parity (思维题 开关问题)

题目大意

给出一个n*n的01方格,现在要求将其中的一些0转换为1,使得每个方格的上下左右格子的数字和为偶数(如果存在的话),求使得最小的转换的个数。

最先想到的是枚举每个方格的状态,非0即1,那么就有2^(n*n)种情况,可见数量之大,必定超时。那么就必须要转换思路。

不难看出这是一个开关问题,就是说可以根据一行的数据,推算出下一行的数据,然后顺次推算出整个格子的数据,之后再来看改变了多少的01序列,求出最小的结果。(稍后会演示推算的算法)。

那么首先就是要枚举第一行的各种情况,这个不难实现。由于题目要求很局限,只是01序列,我们可以采用二进制的方法来依次枚举:

第一行有n个格子,每个格子有2种状态,故需要枚举2^n次。不妨我们先让n为3,看看是如何枚举的。

外层循环是 for i = 0 to (2^3-1)

i = 0 00000000

i = 1 00000001

i = 2 00000010

i = 3 00000011

i = 4 00000100

i = 5 00000101

i = 6 00000110

i = 7 00000111

不难看出 上面的式子中,后3位的情况,正好是我们要枚举的情况。但是我们不能直接取后三位,要想办法,于是问题抓换成:什么时候将某一位(二维数组的某一元素)赋值为1

由于一次只能对1位(二维数组中的一个元素)赋值,我们还需要一层循环, for j = 0 to (n-1) ,再观察下面的式子:

i = 0,j = 0 时 i&(1 << j) =00000000 即为 0

i = 0,j = 1 时 i&(1 << j) = 00000000 即为 0

i = 0,j = 2 时 i&(1 << j) = 00000000 即为0

上面的3式子,可以看做完成了000的赋值。

i = 1,j = 0 时 i&(1 << j) = 00000001 即为1

i = 1,j = 1 时 i&(1 << j) = 00000000 即为 0

i = 1,j = 2 时 i&(1 << j) = 00000000 即为 0

上面的3个式子,可以看做是完成了100的赋值

i = 2,j = 0 时 i&(1 << j) = 00000000 即为 0

i = 2,j = 1 时 i&(1 << j) = 00000000 即为 1

i = 1,j = 2 时 i&(1 << j) = 00000000 即为 0

上面的3个式子,可以看做是完成了010的赋值

……

以此类推,不难看出,这样的2重循环,就完成了对第一行格子的枚举。当然还要注意题目并不允许将1换成0,如果有这样的情况出现,那么要跳过。

现在完成了第一行的枚举。就要根据性质来分别计算第1到n-1行的数据了。依据的性质就是题目中的使得每个方格的上下左右格子的数字和为偶数(如果存在的话),有些读者到此处已经可以大致的写出程序了。大概的算法叙述如下:

我们要算第二行第一列的格子是0还是1,然是并不能直接对这个格子计算,因为他的右边我们还不确定。所以要根据他上一行的格子来计算,由于上一行的格子是在第一行,也就是说他没有上方和左方的格子(这里指的是第一行第一列的格子,若是中间部分的格子,那么只是没有上面的格子,若是第一行最右列的格子,那么他就没有右边和上边的格子),那么求和只需要求右面和下面的格子。而下面的格子又是待求的格子,那么只需要让这个和对2取模,就是这个格子的答案。当然依旧要注意题目并不允许将1换成0。如果有的话,还是要终止这次计算。

(若还有些许不明白,建议看这篇博文:传送门 里面介绍的十分详细)

最后分别求出剩下几行的格子,对比原先的数据,看看改变了多少个01序列。 别忘了上面我们写了一个for循环的枚举,在这么多的情况下,取最小即可,若没有则说明无法打成题目要求,输出-1即可。

代码总览

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define nmax 20
#define INF 0x3f3f3f3f
using namespace std;
int a[nmax][nmax],b[nmax][nmax],n;
int check(int t)
{
memset(b,0,sizeof(b));
//根据传入的参数t来枚举第一行
for(int i = 0; i<n ;++i){
if(t & (1<<i) ) b[0][i] = 1;
else if(a[0][i] == 1) return INF;
}
//依次确定第1至n-1行的内容
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];
b[i][j] = sum % 2;
// 题目中不允许把1 变成 0
if(a[i][j] == 1 && b[i][j] == 0) return INF;
}
}
int ans = 0;
for(int i = 0; i<n; ++i)
for(int j = 0; j<n; ++j)
if(a[i][j] != b[i][j])
ans++;
return ans;
}
int main()
{
int T;
scanf("%d",&T);
for(int cas = 0; cas <T ;cas++){
//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(i));
}
printf("Case %d: ",cas+1);
if(ans == INF) printf("-1\n");
else printf("%d\n",ans);
}
return 0;
}

UVA.11464 Even Parity (思维题 开关问题)的更多相关文章

  1. UVA.11636 Hello World! (思维题)

    UVA.11636 Hello World! (思维题) 题意分析 这题挺水的,还是错了几发. QWQ. 有一个同学打了一行hello world,现在他想打n行hello world,请问最少复制粘 ...

  2. 状态压缩+枚举 UVA 11464 Even Parity

    题目传送门 /* 题意:求最少改变多少个0成1,使得每一个元素四周的和为偶数 状态压缩+枚举:枚举第一行的所有可能(1<<n),下一行完全能够由上一行递推出来,b数组保存该位置需要填什么 ...

  3. 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 in ...

  4. UVa 11464 - Even Parity

    解题报告:题目大意有一个N×N的矩阵,矩阵中的元素只有1或0,如果说对于一个矩阵,它的所有的点的上下左右的点的和是偶数,则称这个矩阵为偶数矩阵,现在给你一个任意的矩阵,要求的是如果要把这个矩阵变成偶数 ...

  5. UVA 11464 Even Parity(部分枚举 递推)

    Even Parity We have a grid of size N x N. Each cell of the grid initially contains a zero(0) or a on ...

  6. UVA 11464 - Even Parity(枚举方法)

    D Even Parity Input: Standard Input Output: Standard Output We have a grid of size N x N. Each cell ...

  7. UVA 11464 - Even Parity 状态压缩,分析 难度: 2

    题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&a ...

  8. 【转载】UVa 11464 Even Parity 偶数矩阵

    题意:给你一个n*n的01矩阵,让你把这个矩阵中尽量少的0转换成1,使得矩阵每个位置的上下左右四个相邻的数加起来能被2整除,求最少的转换数 首先,n 的规模并不大,最大只有15.但是完全枚举整个矩阵显 ...

  9. UVa 11464 Even Parity 偶数矩阵

    给你一个 n * n 的 01 矩阵,现在你的任务是将这个矩阵中尽量少的 0 转化为 1 ,使得每个数的上下左右四个相邻的数加起来是偶数.求最少的转化个数. 首先,n 的规模并不大,最大只有15.但是 ...

随机推荐

  1. 「日常训练」Case of Matryoshkas(Codeforces Round #310 Div. 2 C)

    题意与分析(CodeForces 556C) 为了将所有\(n\)个娃娃编号递增地串在一起(原先是若干个串,每个串是递增的), 我们有两种操作: 拆出当前串中最大编号的娃娃(且一定是最右边的娃娃). ...

  2. fiddler不经意的功能

    捕获指定客户端的请求,直接食用 窗口分离,直接食用 Hide this column  隐藏此列Ensure all columns are visible   显示默认所有列Customize co ...

  3. Codeforces Round #495 (Div. 2) Sonya and Matrix

    正常没有正方形的限制下,值为i的点个数4i 那么从0开始遍历,第一个不为4i的值就是min(x, y) 由于对称性我们姑且令x为这个值 我们先列举n*m=t的各种情况 对于一对n, m.我们已经知道n ...

  4. unity初探之黑暗之光(2)

    unity初探之黑暗之光(2) 一.设置角色跟随鼠标点击移动 思路:使用charactercollider的SimpleMove方法来控制角色的移动.通过摄像机的射线投射到地面,通过屏幕上的一个点也就 ...

  5. 基础的表ADT -数据结构(C语言实现)

    读数据结构与算法分析 表的概述 形如A1,A2,A3... 操作合集 PrintList MakeEmpty Find Insert Delete 表的简单数组实现 分析: PrintList和Fin ...

  6. 学习笔记,99乘法表,嵌套while循环

    line = 0 #定义外循环初变量 while line < 9: #外循环判断语句 line += 1 #改变外循环初变量,避免陷入死循环 row = 0 #定义内循环初变量 while r ...

  7. Windows环境下使用kafka单机模式

    测试运行环境 Win10 kafka_2.11-1.0.0 zookeeper-3.4.10 1.安装Zookeeper Kafka的运行依赖于Zookeeper,所以在运行Kafka之前我们需要安装 ...

  8. 1.编译azkaban

    1.下载azkaban的源码 https://github.com/azkaban/azkaban.git 然后解压得到azkaban-master.zip,解压:unzip azkaban-mast ...

  9. Linux下误删文件恢复办法

    恢复删除的文件 当误删除文件时,如果还有程序对此文件进行操作,那么可以通过lsof 命令恢复文件内容. 举例: 误删粗messages日志文件 [root@cdn ~]# cat /var/log/m ...

  10. 20172330 2017-2018-1 《Java程序设计》第九周学习总结

    20172330 2017-2018-1 <程序设计与数据结构>第九周学习总结 教材学习内容总结 本周的学习包括两章内容,分别为异常和递归. 异常 错误和异常都是对象,代表非正常情况或者无 ...