Fliptile——搜索+二进制优化

【题目描述】

Farmer John knows that an intellectually satisfied cow is a happy cow who will give more milk. He has arranged a brainy activity for cows in which they manipulate an M × N grid (1 ≤ M ≤ 15; 1 ≤ N ≤ 15) of square tiles, each of which is colored black on one side and white on the other side.

As one would guess, when a single white tile is flipped, it changes to black; when a single black tile is flipped, it changes to white. The cows are rewarded when they flip the tiles so that each tile has the white side face up. However, the cows have rather large hooves and when they try to flip a certain tile, they also flip all the adjacent tiles (tiles that share a full edge with the flipped tile). Since the flips are tiring, the cows want to minimize the number of flips they have to make.Help the cows determine the minimum number of flips required, and the locations to flip to achieve that minimum. If there are multiple ways to achieve the task with the minimum amount of flips, return the one with the least lexicographical ordering in the output when considered as a string. If the task is impossible, print one line with the word "IMPOSSIBLE".

Input
Line 1: Two space-separated integers: M and N
Lines 2… M+1: Line i+1 describes the colors (left to right) of row i of the grid with N space-separated integers which are 1 for black and 0 for white
Output
Lines 1… M: Each line contains N space-separated integers, each specifying how many times to flip that particular location.
Sample Input

4 4
1 0 0 1
0 1 1 0
0 1 1 0
1 0 0 1

Sample Output

0 0 0 0
1 0 0 1
1 0 0 1
0 0 0 0

【题目分析】
看完题目后很明显应该是一个暴力搜索,但是应该从哪里开始搜索呢?从头开始的话会有215*15种可能,显然是不允许的。我们应该优化一下搜索的顺序,即哪些情况是显然不可能成立的。
我们如果从上往下搜索,那么下面的对上面的影响只有四个方向中上面的那个,那么如果搜索在x行,那么x-1行中的1下面的那块必须翻转,0下面的那块不能翻转。这样类推,我们发现除了第一行其他行的翻转情况都已经被确定,因此我们只需要枚举第一行的翻转情况(215种)就可以了。
看大佬的博客发现用到一种二进制的优化。如果没有这种优化的话我们可能需要搜索,相对比较复杂。
我们可以将一行中翻转的情况看做一个数,例如:110就是翻转前两个,那么总共的情况就是1<<m种
对于一个数字,我们如何快速判断哪些位是1呢?
我们可以用110与100,010,001的与判断,如果与的结果是0则该位是0,如果结果不是0则该位是1
有上面的方法后我们就可以写出程序啦
【AC代码】(借鉴大佬)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<climits>
#include<string>
#include<queue>
using namespace std;int n,m,num,cnt,ans;
const int MAXN=20;
int a[MAXN][MAXN];		//原数组
int b[MAXN][MAXN];		//用来修改的临时数组
int c[MAXN][MAXN];		//保存答案
const int drc[5][2]={0,0,0,1,0,-1,1,0,-1,0};void rev(int i,int j)
{int u,v;++cnt;  c[i][j]=1;	//记录答案for(int k=0;k<5;k++){u=i+drc[k][0]; v=j+drc[k][1];if(u<0 || u>=n || v<0 || v>=m) continue;b[u][v]^=1;	//翻转}
}bool check(int x)
{cnt=0;memcpy(b,a,sizeof(b));	//直接将a拷贝给bfor(int i=0;i<m;i++){if(x&(1<<(m-1-i)))//1<<(m-1-i)是第i位为1其他位为0的数,用来判断x在第i位是不是1rev(0,i);	//如果是1就翻转}for(int i=1;i<n;i++){for(int j=0;j<m;j++){if(b[i-1][j]) rev(i,j);	//如果上一行是1就翻转}}for(int i=0;i<m;i++){if(b[n-1][i]) return false;	//前面肯定都是0了,只需要判断最后一行是不是0就可以了}return true;
}int main()
{scanf("%d%d",&n,&m);ans=INT_MAX; num=-1;memset(a,0,sizeof(a));for(int i=0;i<n;i++){for(int j=0;j<m;j++){scanf("%d",&a[i][j]);}}for(int i=0,j=1<<m;i<j;i++){if(check(i) && cnt<ans)	//这样记录的答案肯定是字典序,前面的能不翻就不翻,尽量翻后面的{ans=cnt; num=i;}}memset(c,0,sizeof(c));	//用来保存答案,之前都不用保存if(num!=-1){check(num);for(int i=0;i<n;i++){for(int j=0;j<m-1;j++){printf("%d ",c[i][j]);}printf("%d\n",c[i][m-1]);}}else{printf("IMPOSSIBLE");}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384157.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

扫雷

1.将扫雷界面看成一个二维数组,先对界面进行打印 2.置雷 3.排雷 4.对每次的结果进行游戏输出 5.提醒用户游戏输赢 game.c #define _CRT_SECURE_NO_WARNINGS 1 #include"game.h" //初始化 void init_board(char mine[ROWS][COLS], int rows, int cols, char set) {in…

C相关练习题

1.调整数组使奇数全部都位于偶数前面。 输入一个整数数组&#xff0c;实现一个函数&#xff0c;来调整该数组中数字的顺序使得数组中所有的奇数位于数组的前半部分&#xff0c;所有偶数位于数组的后半部分。 #include<stdio.h> void range(int arr[], int sz) {int left…

【C语言】单链表的所有操作的实现(包括PopBack、PushBack、PopFront、PushFront、Insert)

http://blog.csdn.net/hanjing_1995/article/details/51539563 [cpp] view plaincopy #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> using namespace std; //单链表的实现 #include<assert.h> typedef int DataType; typedef…

Shuffle'm Up——简单模拟

【题目描述】 A common pastime for poker players at a poker table is to shuffle stacks of chips. Shuffling chips is performed by starting with two stacks of poker chips, S1 and S2, each stack containing C chips. Each stack may contain chips of several diff…

C++ explicit关键字详解

http://www.cnblogs.com/ymy124/p/3632634.html 首先, C中的explicit关键字只能用于修饰只有一个参数的类构造函数, 它的作用是表明该构造函数是显示的, 而非隐式的, 跟它相对应的另一个关键字是implicit, 意思是隐藏的,类构造函数默认情况下即声明为implicit(隐式). 那么显示声…

Fire!——两个BFS

【题目描述】 【题目分析】 看到题目后很清楚是两个BFS&#xff0c;可是我觉得对于火的BFS可以转换成判断&#xff0c;我的做法是将火的位置全部记录下来&#xff0c;然后判断某个位置距离每个火的步数是否小于当前步数&#xff0c;可是错了&#xff0c;还不清楚为什么&#x…

函数调用过程(栈桢)

栈桢 首先来看一段代码 #include<stdio.h> int add(int x, int y) {int z x y;return z; } int main() {int a 10;int b 20;int ret add(a, b);printf("ret %d\n",ret);return 0; } 此处是为了给a,b分别开辟空间,这时栈桢如图所示 两条push命令将a,b变…

C++智能指针简单剖析

http://blog.csdn.net/lanxuezaipiao/article/details/41603883 导读 最近在补看《C Primer Plus》第六版&#xff0c;这的确是本好书&#xff0c;其中关于智能指针的章节解析的非常清晰&#xff0c;一解我以前的多处困惑。C面试过程中&#xff0c;很多面试官都喜欢问智能指针相…

非常可乐——BFS

【题目描述】 大家一定觉的运动以后喝可乐是一件很惬意的事情&#xff0c;但是seeyou却不这么认为。因为每次当seeyou买了可乐以后&#xff0c;阿牛就要求和seeyou一起分享这一瓶可乐&#xff0c;而且一定要喝的和seeyou一样多。但seeyou的手中只有两个杯子&#xff0c;它们的容…

整型数据存储

//代码1 #include<stdio.h> int main() {char a -1;signed char b -1;unsigned char c -1;printf("a %d, b %d, c %d", a, b, c);return 0; } 1000 0000 0000 0001 -> -1源码 1111 1111 1111 1110 -> -1反码 1111 1111 1111 1111 -> -1补码 对于…

聊聊gcc参数中的-I, -L和-l

http://blog.csdn.net/stpeace/article/details/49408665 在本文中&#xff0c; 我们来聊聊gcc中三个常见的参数&#xff0c; 也即-I, -L和-l 一. 先说 -I (注意是大写的i) 我们先来看简单的程序&#xff1a; main.c: [cpp] view plaincopy #include <stdio.h> #incl…

Pots——BFS

【题目描述】 You are given two pots, having the volume of A and B liters respectively. The following operations can be performed: FILL(i) fill the pot i (1 ≤ i ≤ 2) from the tap; DROP(i) empty the pot i to the drain; POUR(i,j) pour from pot i to pot j;…

HDU - 4578Transformation——线段树+区间加法修改+区间乘法修改+区间置数+区间和查询+区间平方和查询+区间立方和查询

【题目描述】 HDU - 4578Transformation Problem Description Yuanfang is puzzled with the question below: There are n integers, a1, a2, …, an. The initial values of them are 0. There are four kinds of operations. Operation 1: Add c to each number between ax …

[C++基础]034_C++模板编程里的主版本模板类、全特化、偏特化(C++ Type Traits)

http://www.cnblogs.com/alephsoul-alephsoul/archive/2012/10/18/2728753.html 1. 主版本模板类 首先我们来看一段初学者都能看懂&#xff0c;应用了模板的程序&#xff1a; 1 #include <iostream>2 using namespace std;3 4 template<class T1, class T2>5 clas…

自定义类型: 结构体,枚举,联合

1.结构体 个人认为结构体和数组特别相似&#xff0c;只不过结构体和数组的区别在于结构体的成员可以是不同类型&#xff0c;而数组成员类型是相同的。 &#xff08;1&#xff09;结构体的声明 struct tag {成员列表//至少得有一个成员 }值列表;//值列表可以省略 struct {int a…

详解C++中的函数调用和下标以及成员访问运算符的重载

http://www.jb51.net/article/78436.htm 这篇文章主要介绍了详解C中的函数调用和下标以及成员访问运算符,讲到了这些二元运算符使用的语法及重载,需要的朋友可以参考下函数调用 使用括号调用的函数调用运算符是二元运算符。 语法 ?1primary-expression ( expression-list )备…

A计划——BFS

【题目描述】 可怜的公主在一次次被魔王掳走一次次被骑士们救回来之后&#xff0c;而今&#xff0c;不幸的她再一次面临生命的考验。魔王已经发出消息说将在T时刻吃掉公主&#xff0c;因为他听信谣言说吃公主的肉也能长生不老。年迈的国王正是心急如焚&#xff0c;告招天下勇士…

使用openssl的md5库

http://blog.csdn.net/sinat_35297665/article/details/78244523 在linux机器上&#xff0c;有一个命令可以计算出文件的md5值&#xff0c;那就是md5sum&#xff0c;如果没有的话&#xff0c;就需要安装RPM包&#xff1a;coreutils。 现在我们使用openssl的库也可以方便的计算出…

主席树入门

今天学习了一下主席树&#xff08;名字这么强的嘛&#xff09; 虽然直接理解起来不容易&#xff0c;但是这种解决问题的思想其实并不陌生。 我们可以首先来看维护整个区间第K大的线段树 我们将[l,r]区间内数字的多少用线段树进行维护&#xff0c;这样的话为了求取区间第k大&…

Socket网络编程--小小网盘程序(1)

http://www.cnblogs.com/wunaozai/p/3886588.html 这个系列是准备讲基于Linux Socket进行文件传输。简单的文件传输就是客户端可以上传文件&#xff0c;可以从服务器端下载文件。就这么两个功能如果再加上身份验证&#xff0c;就成了FTP服务器了&#xff0c;如果对用户的操作再…