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. Java: Replace a string from multiple replaced strings to multiple substitutes

    Provide helper methods to replace a string from multiple replaced strings to multiple substitutes im ...

  2. 韦大仙--Katalon---一款好用的selenium自动化测试插件

    selenium框架是目前使用较广泛的开源自动化框架,一款好的.基于界面的录制工具对于初学者来说可以快速入门:对于老手来说可以提高开发自动化脚本的效率.我们知道Selenium IDE是一款使用较多的 ...

  3. hackerrank Project Euler #210: Obtuse Angled Triangles

    传送门 做出一个好几个星期屯下来的题目的感觉就是一个字: 爽! 上图的黄点部分就是我们需要求的点 两边的部分很好算 求圆的地方有一个优化,由于圆心是整数点,我们可以把圆分为下面几个部分,阴影部分最难算 ...

  4. 【radio-group、radio】 单选项组件说明

    radio-group组件是包裹radio组件的容器 原型: <radio-group bindchange="[EventHandle]"> <radio .. ...

  5. TW实习日记:第11、12天

    这两天其实都在做一件事,项目组组长丢了个需求下来,要求完成一个百度地图api的页面.原本以为和之前写微信接口的类似,没想到这次问题这么多.并且在写代码的时候和组长交流不畅导致心情也很差,深刻的反思了一 ...

  6. css多行文本溢出显示省略号(…)

    text-overflow:ellipsis属性可以实现单行文本的溢出显示省略号(…).但部分浏览器还需要加宽度width属性. css代码: overflow: hidden; text-overf ...

  7. org.apache.spark.launcher.Main源码分析

    public static void main(String[] argsArray) throws Exception { //org.apache.spark.launcher.Main chec ...

  8. ionic 日期插件学习

    <ion-header> <ion-navbar> <ion-title> DateTime </ion-title> </ion-navbar& ...

  9. 棋盘问题:dfs

    Description 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子 ...

  10. [2018 ACL Short and System] 对话系统

    Short Paper(s) 1.  Task-oriented Dialogue System for Automatic Diagnosis. (Cited by 0) Zhongyu Wei, ...