POJ 3279 Fliptile (二进制+搜索)
【题目链接】click here~~
【题目大意】:
农夫约翰知道聪明的牛产奶多。
于是为了提高牛的智商他准备了例如以下游戏。
有一个M×N 的格子,每一个格子能够翻转正反面,它们一面是黑色,还有一面是白色。黑色的格子翻转后就是白色。白色的格子翻转过来则是黑色。
游戏要做的就是把全部的格子都翻转成白色。
只是由于牛蹄非常大,所以每次翻转一个格子时。与它上下左右相邻接的格子也会被翻转。由于翻格子太麻烦了。所以牛都想通过尽可能少的次数把全部格子都翻成白色。如今给定了每一个格子的颜色。请求出用最小步数完毕时每一个格子翻转的次数。最小步数的解有多个时,输出字典序最小的一组。解不存在的话,则输出IMPOSSIBLE。
【解题思路】:
首先。同一个格子翻转两次的话就会恢复原状,所以多次翻转是多余的。此外。翻转的格子的集合相同的话。其次序是无关紧要的。
因此,总共同拥有2NM种翻转的方法。只是这个解空间太大了,我们须要想出更有效的办法。让我们再回想一下前面的问题。在那道题中,让最左端的牛反转的方法仅仅有1种,于是用直接推断的方法确定就能够了。
相同的方法在这里还行得通吗?最好还是先看看最左上角的格子。
在这里。除了翻转(1,1)之外,翻转(1,2)和(2,1)也能够把这个格子翻转,所以像之前那样直接确定的办法行不通。于是最好还是先指定好最上面一行的翻转方法。此时能够翻转(1,1)的仅仅剩下(2,1)了,所以能够直接推断(2,1)是否须要翻转。类似地(2,1)~(2,N)都能这样推断。如此重复下去就能够确定全部格子的翻转方法。最后(M,1)~(M,N)假设并不是全为白色,就意味着不存在可行的操作方法。像这样。先确定第一行的翻转方式,然后能够非常easy推断这样是否存在解以及解的最小步数是多
少,这样将第一行的全部翻转方式都尝试一次就能求出整个问题的最小步数。
这个算法中最上面一行的翻转方式共同拥有2N种,复杂度为O(MN2N)。
代码:
- // C
- #ifndef _GLIBCXX_NO_ASSERT
- #include <cassert>
- #endif
- #include <cctype>
- #include <cerrno>
- #include <cfloat>
- #include <ciso646>
- #include <climits>
- #include <clocale>
- #include <cmath>
- #include <csetjmp>
- #include <csignal>
- #include <cstdarg>
- #include <cstddef>
- #include <cstdio>
- #include <cstdlib>
- #include <cstring>
- #include <ctime>
- #if __cplusplus >= 201103L
- #include <ccomplex>
- #include <cfenv>
- #include <cinttypes>
- #include <cstdalign>
- #include <cstdbool>
- #include <cstdint>
- #include <ctgmath>
- #include <cwchar>
- #include <cwctype>
- #endif
- // C++
- #include <algorithm>
- #include <bitset>
- #include <complex>
- #include <deque>
- #include <exception>
- #include <fstream>
- #include <functional>
- #include <iomanip>
- #include <ios>
- #include <iosfwd>
- #include <iostream>
- #include <istream>
- #include <iterator>
- #include <limits>
- #include <list>
- #include <locale>
- #include <map>
- #include <memory>
- #include <new>
- #include <numeric>
- #include <ostream>
- #include <queue>
- #include <set>
- #include <sstream>
- #include <stack>
- #include <stdexcept>
- #include <streambuf>
- #include <string>
- #include <typeinfo>
- #include <utility>
- #include <valarray>
- #include <vector>
- #if __cplusplus >= 201103L
- #include <array>
- #include <atomic>
- #include <chrono>
- #include <condition_variable>
- #include <forward_list>
- #include <future>
- #include <initializer_list>
- #include <mutex>
- #include <random>
- #include <ratio>
- #include <regex>
- #include <scoped_allocator>
- #include <system_error>
- #include <thread>
- #include <tuple>
- #include <typeindex>
- #include <type_traits>
- #include <unordered_map>
- #include <unordered_set>
- #endif
- using namespace std;
- #define rep(i,j,k) for(int i=(int)j;i<(int)k;++i)
- #define per(i,j,k) for(int i=(int)j;i>(int)k;--i)
- #define lowbit(a) a&-a
- #define Max(a,b) a>b?a:b
- #define Min(a,b) a>b?
- b:a
- #define mem(a,b) memset(a,b,sizeof(a))
- typedef long long LL;
- typedef unsigned long long LLU;
- typedef double db;
- const int N=16;
- const int inf=0x3f3f3f3f;
- int n,m,t,ans,res,cnt,tmp;
- char str[N];
- bool vis[N];
- int mat[N][N];///状态之前
- int flip[N][N];///状态中间
- int Res[N][N];///状态之后
- int dir4[4][2]= {{1,0},{0,1},{-1,0},{0,-1}};
- int dir8[8][2]= {{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1},{0,-1},{1,-1}};
- int movv[5][2]= {{1,0},{0,1},{0,0},{-1,0},{0,-1}};
- using namespace std;
- inline LL read()
- {
- int c=0,f=1;
- char ch=getchar();
- while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
- while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
- return c*f;
- }
- bool ok(int dx,int dy)
- {
- if(dx>=0&&dx<n&&dy>=0&&dy<m) return true;
- return false;
- }
- void getMat()///输入
- {
- for(int i=0; i<n; ++i)
- for(int j=0; j<m; ++j)
- scanf("%d",&mat[i][j]);
- }
- int getChange(int x,int y)///推断x,y的颜色
- {
- int c=mat[x][y];
- for(int i=0; i<5; ++i)
- {
- int dx=x+movv[i][0];
- int dy=y+movv[i][1];
- if(ok(dx,dy))c+=flip[dx][dy];
- }
- return c&1;///奇数为1。偶数为0
- }
- int calc()
- {
- ///求出第二行開始的翻转方法
- for(int i=1; i<n; ++i){
- for(int j=0; j<m; ++j){
- if(getChange(i-1,j)!=0)///是白色翻转
- flip[i][j]=1;
- }
- }
- ///推断最后一行是否全白
- for(int j=0; j<m; ++j){
- if(getChange(n-1,j)!=0)
- return -1;
- }
- int sum=0;///统计翻转次数
- for(int i=0; i<n; ++i){
- for(int j=0; j<m; ++j){
- sum+=flip[i][j];
- }
- }
- return sum;
- }
- void solve()
- {
- int res=inf;
- for(int i=0; i< (1<<m); ++i){///枚举第一行的情况
- mem(flip,0);
- for(int j=0; j<m; j++){
- flip[0][m-j-1] = i >> j & 1;
- }
- int now=calc();
- if(now>=0&&now<res){
- res=now;
- memcpy(Res,flip,sizeof(flip));
- }
- }
- if(res!=inf){
- for(int i=0; i<n; ++i){
- for(int j=0; j<m; ++j){
- printf("%d%c",Res[i][j],j==m-1?
- '\n':' ');
- }
- }
- }
- else puts("IMPOSSIBLE");
- }
- int main()
- {
- while(cin>>n>>m){
- getMat();
- solve();
- }
- return 0;
- }
- </span>
POJ 3279 Fliptile (二进制+搜索)的更多相关文章
- poj 3279 Fliptile(二进制搜索)
Farmer John knows that an intellectually satisfied cow is a happy cow who will give more milk. He ha ...
- POJ.3279 Fliptile (搜索+二进制枚举+开关问题)
POJ.3279 Fliptile (搜索+二进制枚举+开关问题) 题意分析 题意大概就是给出一个map,由01组成,每次可以选取按其中某一个位置,按此位置之后,此位置及其直接相连(上下左右)的位置( ...
- poj 3279 Fliptile (简单搜索)
Fliptile Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 16558 Accepted: 6056 Descrip ...
- poj 3279 Fliptile(二进制)
http://poj.org/problem?id=3279 在n*N的矩阵上,0代表白色,1代表黑色,每次选取一个点可以其颜色换过来,即白色变成黑色,黑色变成白色,而且其上下左右的点颜色也要交换,求 ...
- POJ 3279 Fliptile[二进制状压DP]
题目链接[http://poj.org/problem?id=3279] 题意:给出一个大小为M*N(1 ≤ M ≤ 15; 1 ≤ N ≤ 15) 的图,图中每个格子代表一个灯泡,mp[i][j] ...
- POJ 3279 Fliptile (二进制枚举)
<题目链接> <转载于 >>> > 题目大意: 给定一个M*N矩阵,有些是黑色(1表示)否则白色(0表示),每翻转一个(i,j),会使得它和它周围4个格变为另 ...
- POJ 3279 Fliptile(翻格子)
POJ 3279 Fliptile(翻格子) Time Limit: 2000MS Memory Limit: 65536K Description - 题目描述 Farmer John kno ...
- 状态压缩+枚举 POJ 3279 Fliptile
题目传送门 /* 题意:问最少翻转几次使得棋子都变白,输出翻转的位置 状态压缩+枚举:和之前UVA_11464差不多,枚举第一行,可以从上一行的状态知道当前是否必须翻转 */ #include < ...
- POJ 3279(Fliptile)题解
以防万一,题目原文和链接均附在文末.那么先是题目分析: [一句话题意] 给定长宽的黑白棋棋盘摆满棋子,每次操作可以反转一个位置和其上下左右共五个位置的棋子的颜色,求要使用最少翻转次数将所有棋子反转为黑 ...
随机推荐
- TF卡翻盖式卡座
- python爬虫beautifulsoup4系列4-子节点
前言 很多时候我们无法直接定位到某个元素,我们可以先定位它的父元素,通过父元素来找子元素就比较容易 一.子节点 1.以博客园首页的摘要为例:<div class="c_b_p_desc ...
- 浏览器User-Agent的详细信息
PC端: safari 5.1 – MACUser-Agent:Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit ...
- KB/KiB,MB/MiB,GB/GiB了解一下
Kibibyte是一种资讯计量单位,代表1024字节,即210字节,一般简称为KiB.Kibibyte是来自英文 kilo binary byte 的缩写,意思为“千位二进制字节”. 而KB是kilo ...
- Guava的使用
package guava; import java.io.File; import java.io.IOException; import java.util.ArrayList; import j ...
- fonts.conf 中文手册
FONTS-CONF(5) FONTS-CONF(5) 名称 fonts.conf -- 字体配置文件 文件概要 /etc/fonts/fonts.conf /etc/fonts/fonts.dtd ...
- Unity3D 浅谈被忽略的Quality [转]
开始分享之前,我先墨迹几句... 最近在工作上,在交流群中,都会遇到一些问题.比如: 为什么打包Android Apk以后,图片变模糊了? 为什么移动端的阴影和电脑端不一样? 我的电脑明明配置很好,为 ...
- NPOI导出Excel时出现错误“Maximum column number is 255”
此错误并不是NPOI的问题,而是Excel的问题,原因是Excel的最大列255,所以导出的列超过255时就会出现此问题 但Excel2007以上并没有此问题,因为2007以上的列已经增加到16384 ...
- Android开发者指南(9) —— ProGuard
转: 前言 本章内容为开发者指南(Dev Guide)/Developing/Tools/ProGuard,本章内容为"混淆器",版本为Android3.0 r1,翻译来自:&qu ...
- hihoCoder 1261 String Problem II
时间限制:50000ms 单点时限:5000ms 内存限制:512MB 描写叙述 我们有一个字符串集合S,当中有N个两两不同的字符串.还有M个询问,每一个询问都会先给出一个字符串w,你须要回答下面三个 ...