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. generator-ivweb 基于react-redux的多页脚手架

    背景 每个公司甚至每个项目组,在开发新项目的时候都会有一些自己特色的东西,比如公共组件,ajax请求拦截处理,内部积累的一些业务逻辑等等,如果没有自己的脚手架,那么拷贝代码成为常态,每个项目的结构,甚 ...

  2. Qt-Qml-播放视频-失败版-只有声音没有图像

    失败版代码 import QtQuick 2.7 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.0 import QtMultimedia ...

  3. svn清理报错:Cleanup failed to process the following paths

    这里碰到svn更新时,提示清理,清理时报错: 只需进行以下几个步骤即可解决:(原理即是清除掉svn数据库里的lock记录) 1.下载SQLiteManager,svn用的是sqlite数据库,需要一款 ...

  4. ObjectMapper的使用

    Jackson ObjectMapper类 ObjectMapper类是Jackson库的主要类它提供一些功能将Java对象转换成JSON结构,反之亦然它使用JsonParser和JsonGenera ...

  5. JavaScript --经典问题

    JavaScript中如何检测一个变量是一个String类型?请写出函数实现 方法1. function isString(obj){ return typeof(obj) === "str ...

  6. python图片大小处理;

    循环一个目录将下面的所有png或者jpg文件全部缩小一定比例:     from PIL import Image import os,re work_dir = 'C:\\Users\\Admini ...

  7. smartgit 使用

    合并分支

  8. 如何借助windows的VHD引导特性实现VHD多windows系统共存

    近期,由于一些需要,需要运行3个windows系统,具体需要如何此处略去,现将实现方式共享如下. 测试环境: HP 820 G2, 4G内存, 500G SSD硬盘 windows 7 企业版 win ...

  9. Trie 树——搜索关键词提示

    当你在搜索引擎中输入想要搜索的一部分内容时,搜索引擎就会自动弹出下拉框,里面是各种关键词提示,这个功能是怎么实现的呢?其实底层最基本的就是 Trie 树这种数据结构. 1. 什么是 "Tri ...

  10. 四、oracle 用户管理二

    一.使用profile管理用户口令概述:profile是口令限制,资源限制的命令集合,当建立数据库时,oracle会自动建立名称为default的profile.当建立用户没有指定profile选项时 ...