今天距离我上次写文章已经有10天了,并不是我上个星期没学新知识,是我被一道题整整卡了10天,这道题就是我今天的主题——偶数矩阵。
原题如下:
给你一个n*n的01矩阵(每个元素非0即1),你的任务是把尽量少的0变成1,使得每个元素的上、下、左、右的元素(如果存在的话)之和均为偶数。如图所示的矩阵至少要把3个0变成1,最终如图所示,才能保证其为偶数矩阵。
【输入格式】 输入的第一行为数据组数T(T<30)。每组数据的第一行为正整数n(1 < n < 15);接下来的n行每行包含n个非0即1的整数,相邻整数间用一个空格隔开。
【输出格式】 对于每组数据,输出被改变的元素的最小个数。如果无解,应输出-1。
既然被难了那么久,而且我竟然还沦落到连书上和别人在网上的博客的答案都看不懂的地步了,我就要完完整整,清清楚楚的把这个问题说明白,我敢保证这是所有网上博客中比较通俗易懂的。刚拿到这题时,我的思路很简单,既然只有0变成1这种情况,那么就从矩阵中为零的元素入手,当这些为零的元素确定下来了,整个矩阵也就确定了。刚开始我还没有进行严格的数学分析,通过对每一个矩阵中的元素进行分析,确定每一个零元素可能要变的次数,我称之为权值,误以为权值最大的,表明其变为1的迫切性就越大,可事实是通过对矩阵中的每一个元素进行分析,有的0元素必须变成1,而有的0则一定不能变成1,比如说:
0 1 1 0
1 0 0 1
0 0 1 0
1 0 0 0
红色的0就是必须变为1的,而绿色的0是一定不能变为1的。
这样思路就很直接了:找出必须改的0,确定一定不能改为1的0。
从以下三种情况退出必须改的0元素
(1)
0 0 (2) 1 (3) 1
1 1 1 1
0 0
顺着这样的思路,我
就开始了第一次程序的编写,如下:
#include <iostream>
#include <cstdio>
using namespace std;
const int maxn = 15;
struct node
{
int text; //不是0就是1
bool statement; //false表示不能修改,初始值为true
bool changeable; //是否为必须修改元素
}A[maxn][maxn];
bool isDouble(struct node A[][maxn],int n) //检验此时的数组,是否已成为偶数矩阵
{
for(int i = 0;i<n;++i)
{
for(int j =0;j<n;++j)
{
if( (i-1)<0 && (j+1) == 1 )
{
if(A[i+1][j] + A[i][j+1] == 2)
continue;