【题目链接】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 (二进制+搜索)的更多相关文章

  1. poj 3279 Fliptile(二进制搜索)

    Farmer John knows that an intellectually satisfied cow is a happy cow who will give more milk. He ha ...

  2. POJ.3279 Fliptile (搜索+二进制枚举+开关问题)

    POJ.3279 Fliptile (搜索+二进制枚举+开关问题) 题意分析 题意大概就是给出一个map,由01组成,每次可以选取按其中某一个位置,按此位置之后,此位置及其直接相连(上下左右)的位置( ...

  3. poj 3279 Fliptile (简单搜索)

    Fliptile Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 16558   Accepted: 6056 Descrip ...

  4. poj 3279 Fliptile(二进制)

    http://poj.org/problem?id=3279 在n*N的矩阵上,0代表白色,1代表黑色,每次选取一个点可以其颜色换过来,即白色变成黑色,黑色变成白色,而且其上下左右的点颜色也要交换,求 ...

  5. POJ 3279 Fliptile[二进制状压DP]

    题目链接[http://poj.org/problem?id=3279] 题意:给出一个大小为M*N(1 ≤ M ≤ 15; 1 ≤ N ≤ 15) 的图,图中每个格子代表一个灯泡,mp[i][j] ...

  6. POJ 3279 Fliptile (二进制枚举)

    <题目链接> <转载于 >>> > 题目大意: 给定一个M*N矩阵,有些是黑色(1表示)否则白色(0表示),每翻转一个(i,j),会使得它和它周围4个格变为另 ...

  7. POJ 3279 Fliptile(翻格子)

    POJ 3279 Fliptile(翻格子) Time Limit: 2000MS    Memory Limit: 65536K Description - 题目描述 Farmer John kno ...

  8. 状态压缩+枚举 POJ 3279 Fliptile

    题目传送门 /* 题意:问最少翻转几次使得棋子都变白,输出翻转的位置 状态压缩+枚举:和之前UVA_11464差不多,枚举第一行,可以从上一行的状态知道当前是否必须翻转 */ #include < ...

  9. POJ 3279(Fliptile)题解

    以防万一,题目原文和链接均附在文末.那么先是题目分析: [一句话题意] 给定长宽的黑白棋棋盘摆满棋子,每次操作可以反转一个位置和其上下左右共五个位置的棋子的颜色,求要使用最少翻转次数将所有棋子反转为黑 ...

随机推荐

  1. 设计模式 - 观察者模式(Observer Pattern) Java内置 用法

    观察者模式(Observer Pattern) Java内置 用法 本文地址: http://blog.csdn.net/caroline_wendy/article/details/26601659 ...

  2. Cocos2d-x3.0 解压zip

    2dx3.0为我们集成了unzip库,帮助我们实现对文件的解压,但使用起来略显复杂我这里封装了一个解压工具库.分享一下. 工具类下载:http://download.csdn.net/detail/q ...

  3. 更改CentOS 6.3 yum源为国内 阿里云源

    将CentOS的 yum源 更换为 阿里云源 1.备份 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.b ...

  4. jdk1.8 foreach

    lambda 表达式效率非常低,测试代码可以看到大概3~5倍的差距 遍历Map的方式有很多,通常场景下我们需要的是遍历Map中的Key和Value,那么推荐使用的: public static voi ...

  5. C语言跟内存分配方式-alloc malloc calloc

    转载:http://blog.csdn.net/ubuntulover/article/details/7581317 (1) 从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整 ...

  6. [翻译] SoundManager 音频管理器

    SoundManager 音频管理器 https://github.com/nicklockwood/SoundManager Purpose SoundManager is a simple cla ...

  7. 在Qt示例项目的C ++ / QML源中的//! [0]的含义是什么?

    在Qt示例项目的C ++ / QML源中的//! [0]的含义是什么? 例如:  //! [0] GLWidget :: GLWidget(Helper * helper,QWidget * pare ...

  8. .NET-MVC站点发布注意事项

    在进行MVC站点发布的过程中需要注意bin文件,使用vs2013自带的发布功能容易漏掉一些dll文件,所以在发布之后需要将程序的bin目录下的文件拷贝到发布好的iis站点下面

  9. 关于substring的char[]共享

    我们知道,对于一个较大的String对象假设从中获取一个子串.jdk默认子串的char[]是共享原串的char[].即子串的char[]是原串的char[]中的一部分, 这样对于一个原串多个子串的情况 ...

  10. Grunt的配置及使用(压缩合并js/css)

    Grunt的配置及使用(压缩合并js/css) 安装 前提是你已经安装了nodejs和npm. 你能够在 nodejs.org 下载安装包安装.也能够通过包管理器(比方在 Mac 上用 homebre ...