UVa 11464 Even Parity 偶数矩阵
给你一个 n * n 的 01 矩阵,现在你的任务是将这个矩阵中尽量少的 0 转化为 1 ,使得每个数的上下左右四个相邻的数加起来是偶数。求最少的转化个数。
首先,n 的规模并不大,最大只有15。但是完全枚举整个矩阵显然是不可能的(2225 ≈ 5 * 1067)。但是我们可以枚举第一行,然后用第一行来算出后面的所有行。
但是,怎么算呢?
先来说下算法。对于每一行,我们通过他上面的两行来决定他的值。如果上面两行得到值为奇数,那么这一行就赋值为 1 ,否则赋值为 0 。 然后与原始矩阵比较,如果是由 1 变 0 那么这种情况是不允许的,于是继续枚举第一行,重新计算后面的。如果是由 0 变 1(或不变) 那么保存下来。最后在计算所有的格子之后,遍历一下就能统计转化数。然后取最小值就可以了。
下面用题目中给的第二组数据来演示一下如何通过上一行来计算下一行。
问题 正解
0 0 0 ==> 0 1 0
1 0 0 ==> 1 0 1
0 0 0 ==> 0 1 0
来举例说明。首先我们通过枚举第一行可以达到以下情况
| 0 | 1 | 0 |
如下表我们开始通过第一行来计算第二行,对于 x 所在的这一格来说,把这一格当做他上面一格的下面相邻的格子进行计算,于是对于第一行第一列来说,他上下左右相加起来为 1 + x,因为要保证是偶数,所以 x = 1。接着与原矩阵进行比较,是符合题目要求的转化(不变)。保留,继续计算下一个。
| 0 | 1 | 0 |
| x | ||
如下表开始计算第二行第二列,按照上面的方法,计算得出 0 + 0 + x 要为偶数,所以 x = 0。与原数组比较依旧是符合题目要求的。
| 0 | 1 | 0 |
| 1 | x | |
如下表计算第二行第三列,同上,得出 1 + x 要为偶数,所以 x = 1。与原矩阵比较,发现是符合要求的转化(0 变 1)继续。
| 0 | 1 | 0 |
| 1 | 0 | x |
这样第二行就得出来了,是下面这种情况:
| 0 | 1 | 0 |
| 1 | 0 | 1 |
按照上述方法,可以计算出第三行,来完成这个例子的答案:
| 0 | 1 | 0 |
| 1 | 0 | 1 |
| 0 | 1 | 0 |
最后在说一下枚举第一行的 2 种方法,第一个种自然是直接深度优先搜索(DP)直接进行枚举。第二种可以利用位运算(末尾附上的AC代码采用的方法)进行枚举。因为整数在内存中是用二进制存储的。只要让 s 从 0 开始一直加到 2n-1 – 1 这么大就可以枚举所有的情况。具体实现可以参看我的代码。
附AC代码
1: #include <stdio.h>
2: #include <math.h>
3: #include <iostream>
4: #include <cstdarg>
5: #include <algorithm>
6: #include <string.h>
7: #include <stdlib.h>
8: #include <string>
9: #include <list>
10: #include <vector>
11: #include <map>
12: #define LL long long
13: #define M(a) memset(a, 0, sizeof(a))
14: using namespace std;
15:
16:
17: const int MAXLEN = 19, INF = 99999999;
18: int T, n, f;
19: int a[MAXLEN][MAXLEN], b[MAXLEN][MAXLEN];
20:
21: void Clean(int count, ...)
22: {
23: va_list arg_ptr;
24: va_start (arg_ptr, count);
25: for (int i = 0; i < count; i++)
26: M(va_arg(arg_ptr, char*));
27: va_end(arg_ptr);
28: }
29:
30: int Deal(int s)
31: {
32: M(b);
33: int t = s;
34: for (int k = 1; k <= n; k++)
35: {
36: if (1 & t) b[1][k] = 1;
37: else if (a[1][k] == 1) return INF;
38: t = t >> 1;
39: }
40: for (int r = 2; r <= n; r++)
41: {
42: for (int c = 1; c <= n; c++)
43: {
44: int sum = 0;
45: if (r > 2) sum += b[r - 2][c];
46: if (c > 1) sum += b[r - 1][c - 1];
47: if (c < n) sum += b[r - 1][c + 1];
48: b[r][c] = sum % 2;
49: if (a[r][c] == 1 && b[r][c] == 0) return INF;
50: }
51: }
52: int cnt = 0;
53: for (int r = 1; r <= n; r++)
54: for (int c = 1; c <= n; c++)
55: if (a[r][c] != b[r][c]) cnt += 1;
56: return cnt;
57: }
58:
59: int main()
60: {
61: int cnt = 1;
62: scanf("%d", &T);
63: while (T--)
64: {
65: scanf("%d", &n);
66: for (int i = 1; i <= n; i++)
67: for (int j = 1; j <= n; j++)
68: scanf("%d", &a[i][j]);
69: int m = INF;
70: for (int s = 0; s < (1 << n); s++)
71: m = min(m, Deal(s));
72: if (m == INF) m = -1;
73: printf("Case %d: %d\n", cnt++, m);
74: }
75: return 0;
76: }
UVa 11464 Even Parity 偶数矩阵的更多相关文章
- 【转载】UVa 11464 Even Parity 偶数矩阵
题意:给你一个n*n的01矩阵,让你把这个矩阵中尽量少的0转换成1,使得矩阵每个位置的上下左右四个相邻的数加起来能被2整除,求最少的转换数 首先,n 的规模并不大,最大只有15.但是完全枚举整个矩阵显 ...
- UVA.11464 Even Parity (思维题 开关问题)
UVA.11464 Even Parity (思维题 开关问题) 题目大意 给出一个n*n的01方格,现在要求将其中的一些0转换为1,使得每个方格的上下左右格子的数字和为偶数(如果存在的话),求使得最 ...
- 状态压缩+枚举 UVA 11464 Even Parity
题目传送门 /* 题意:求最少改变多少个0成1,使得每一个元素四周的和为偶数 状态压缩+枚举:枚举第一行的所有可能(1<<n),下一行完全能够由上一行递推出来,b数组保存该位置需要填什么 ...
- 【巧妙算法系列】【Uva 11464】 - Even Parity 偶数矩阵
偶数矩阵(Even Parity, UVa 11464) 给你一个n×n的01矩阵(每个元素非0即1),你的任务是把尽量少的0变成1,使得每个元素的上.下.左.右的元素(如果存在的话)之和均为偶数.比 ...
- 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 ...
- 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 ...
- UVa 11464 - Even Parity
解题报告:题目大意有一个N×N的矩阵,矩阵中的元素只有1或0,如果说对于一个矩阵,它的所有的点的上下左右的点的和是偶数,则称这个矩阵为偶数矩阵,现在给你一个任意的矩阵,要求的是如果要把这个矩阵变成偶数 ...
- UVA 11464 - Even Parity(枚举方法)
D Even Parity Input: Standard Input Output: Standard Output We have a grid of size N x N. Each cell ...
- UVA 11464 - Even Parity 状态压缩,分析 难度: 2
题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&a ...
随机推荐
- 2014多校第六场 1005 || HDU 4925 Apple Tree
题目链接 题意 : 给你一块n×m的矩阵,每一个格子可以施肥或者是种苹果,种一颗苹果可以得到一个苹果,但是如果你在一个格子上施了肥,那么所有与该格子相邻(指上下左右)的有苹果树的地方最后得到的苹果是两 ...
- (4)用opengl读入off文件生成可执行文件把模型显示出来(未完待续)
·找了好几个程序,好像都达不到我的要求,去教程里看看吧! 在往上抛出了这问题,好几天才有人回答,我已经找到程序了 正好的他的分析对我分解程序很有用 这是一个难度比较高的 首先你要分析.off文件结构, ...
- android自动化环境搭建
android自动化环境安装指南 1.appium相关安装(eclipse下)见http://www.cnblogs.com/wangcp-2014/p/5717589.html参考selenium的 ...
- poj3415 Common Substrings(后缀数组,单调栈 | 后缀自动机)
[题目链接] http://poj.org/problem?id=3415 [题意] A与B长度至少为k的公共子串个数. [思路] 基本思想是将AB各个后缀的lcp-k+1的值求和.首先将两个字符串拼 ...
- windows条件下,Ping加上时间戳,并保存到文件,适用于测试网络
在c盘下面新建文件 ping.vbs 在 ping.vbs中输入代码如下: Dim args, flag, unsuccOut args="" otherout="&qu ...
- sql server2008禁用远程连接
1.打开SQL Server 配置管理器,双击左边 SQL Server 网络配置,点击TCP/IP协议,在协议一栏中,找到 全部侦听,修改为否,然后点击IP地址,将IP地址为127.0.0.1(IP ...
- Qt之QSpacerItem(控件之间的间距不尽相同,可以借助QSpacerItem来设置,并且还可以对QSpacerItem设置QSizePolicy)
http://blog.csdn.net/u011012932/article/details/51614868
- 使用 Dalvik 调试监控服务 (DDMS) 工具
Android 附带一个叫Dalvik 调试监控服务 (DDMS) 的调试工具,它提供端口转发服务.在设备上的屏幕捕获,设备上的线程和堆栈信息, logcat,进程, 和无线状态信息,接收呼叫和SMS ...
- VI操作--跳到最后一行和跳到最后一行的最后一个字符
vi操作 1.跳到文本的最后一行:按“G”,即“shift+g” 2.跳到最后一行的最后一个字符 : 先重复1的操作即按“G”,之后按“$”键,即“shift+4”. 3.跳到第一行的第一个字符:先按 ...
- Xlib: connection to ":0.0" refused by server Xlib: No protocol specified解决方案
Xlib: connection to ":0.0" refused by server Xlib: No protocol specified 解决办法: 1. 退出oracl ...