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)题解
以防万一,题目原文和链接均附在文末.那么先是题目分析: [一句话题意] 给定长宽的黑白棋棋盘摆满棋子,每次操作可以反转一个位置和其上下左右共五个位置的棋子的颜色,求要使用最少翻转次数将所有棋子反转为黑 ...
随机推荐
- Mastering stack and heap for system reliability
http://www.iar.com/Global/Resources/Developers_Toolbox/Building_and_debugging/Mastering_stack_and_he ...
- [js插件]分享一个文章内容信息提示插件Colortip
引用 项目中需要一个信息提示的功能,就上网找了一个插件,发现colortip实现比较简单,就定了这个插件. 实现过程 官网:http://tutorialzine.com/2010/07/colort ...
- JavaScript面向对象编程指南(第2版)》读书笔记
一.对象 1.1 获取属性值的方式 water = { down: false } console.log(water.down) // false console.log(water['down'] ...
- node升级后,项目中的node-sass报错的问题
之前可能因为电脑不知道哪抽风了,在npm build的时候进入就卡在入口的地方,启动express的时候也会,所以就重装了一下node 重装node 其实也不是重装,就是使用 where node 查 ...
- CAS3.5.x(x>1)支持OAuth2 server
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...
- Model工具
Sybase PowerDesigner - 一个高端数据建模工具.你可以下载一个45天试用版. ERWin - 一个高端数据建模工具.可下载试用版. Rational Rose Enterprise ...
- Appium+python自动化55-appium desktop每次启动安装Unlock和Appium Setting问题
前言 部分真机可能会出现每次运行代码,启动app之前都会重复安装Unlock和Appium Setting这两个小工具,有的手机会自动安装,这个还好. 有的手机每次都会弹出一个安装确认框(如部分小米和 ...
- 百度地图js小结
1.获取javascript API 服务方法,首先申请密钥(ak),才可成功载入APIJS文件. 用法例如以下: <script type="text/javascript" ...
- Birt中实现字段拆分为表的还有一种方法
来源: http://developer.actuate.com/community/forum/index.php? /topic/36204-split-data-row/. 将字段拆分为 ...
- gdb对应vc调试命令
gdb vc调试对照表: 实现功能 vc gdb 修改后编译 f7 ma ...