POJ1222、POJ3279、POJ1753--Flip
为什么将着三个题放一起讲呢?因为只要搞明白了其中一点,就可以一次3ac了~~
首先讲下每个题目的意思
1.EXTENDED LIGHTS OUT




给你5行6列的01矩阵,0代表该点的灯是关闭的,1代表该点的灯是开着的,要求出每一栈灯是否按下,使得所有的灯都熄灭,当然,按下某一盏灯时,它附近的灯也会变成原来相反的状态,如图所示。
2.Fliptile
一群奶牛,喜欢白色瓷砖,输入n*m的01矩阵,0表示白色,1表示黑色,问每个砖块该怎么翻转,最后使得所有的颜色都是白色,要求对应的翻转的矩阵对应的字典序最小。每翻转一个,周围的也会变化。如果不可以输出IMPOSSIBLE
3.Flip Game


问你针对途中黑白色圈圈,输出将图中所有的颜色全部变成白色或全部变成黑色的最小的一种翻转次数。
如果怎么都翻转失败,输出Impossible
通过三个题目意思得知,它们有共同点。最后都要求最后是同一种颜色,而且翻转一个点势必会影响周围的四个的原来的颜色状态
除了第一个,二三都存在Impossible的情况。
下面开始介绍思路(假设求解把所有的点变为0|白色的翻转方案),对于n*m个格子,每个格子对应有2中状态,那么,我把所有的状态都搜索一遍,找出合适的翻转方案可以不??当然可以,但是十有八九会T掉。因为光4*4的矩阵就由2^16种状态了,更别说大一点的了。所以暴搜是不可取的。

对于每一种操作,都会对应上述这样情况,那我们该从哪个点开始呢??
因为题目要求矩阵中所有的点都变为同一色,而每个操作互相影响,所以搜索要一行一行来,但是如果后一行的全为0,当前行的某一个操作又影响到上一行和下一行,那后面的又白费了,这样要搞到什么时候??
试想一下,如果第一行的翻转方案确定了,那么第一行的翻转势必影响到第二行的翻转,第二行的翻转也会影响到第三行的翻转,一直到最后一行。。。也就是说,第一行的翻转方案会影响到整个翻转的结果。
而第一行的翻转状态有多少呢??只有2^m(列号)(用二进制对应每个点的状态)个,这比搜索所有的状态要少多了。
我们还要看一个问题,因为每个点的状态只有两个,0和1,自己翻转肯定改变自己的状态,也会影响周围临近4个点的状态,周围的翻转也会影响自己。但是,有个次数的问题。就如同灯开了2次,4次,6次...到最后还是恢复成原来的状态了。
即如果当前自己为1,自己加周围4个总共翻转了5次,那么自己变成了几???5次后,自己变成了0。也就是说,这个点在周围和自己的影响下,变成了目标(0)的状态,那么,这个点还用去翻转吗??当然不用了
如果是0,一样的道理,所以总结出一点:若cnt表示当前点的状态信息(0|1),sum表示自己加周围临近的4个的所有翻转次数,那么最终这一点是否要翻转取决于(cnt +sum)% 2的值.
当前是1,临近点加自己总共翻转5次,那么自己变成0。即最终自己不需要额外翻转一次
当前是1,临近点加自己总共翻转4次,那么自己变成1,最后自己要多翻转一次才能变成0
当前是0,临近点加自己总共翻转5次,自己变成1,那么自己要多翻转一次才能变成0
当前是0,临近点加自己总共翻转4次,那么自己变成0,不需要额外翻转了
得出结论,当前点是否需要翻转取决于 (原来自己的状态+所有对自己起作用的翻转数) % 2, 结果为1表明要翻转,为0表明不需要了。这里不清楚的可以自己多写几个看看
好了,第一行的状态数知道了,即每个点的怎么翻转知道了,该怎么求最终结果呢??
因为已经知道了第一行的所有翻转方案(0 ~ 2^m-1个),那么对所有方案搜索,直到最后一行的所有的翻转方案都是0就表明第一行的翻转方案是可取的了。。。这什么意思呢
如果搜索到最后,发现最后一行存在几个数是需要翻转的,即这几个数是在上层的翻转作用下变成了1,最后还需要把这几个1翻转一下才会变成0,但是,当你翻转这几个1,势必又影响到上一层,结果上一层又出现几个1。再往上翻,就打乱了所有的状态。所以第一行的翻转方案一定是不可行的。
要点:在第一行的翻转方案搜索中,通过搜索第一行的翻转方案,用第二行的翻转去改变第一行的状态(将1变为0)。接下来的每一行继续用下一行去调整但前行的状态,直至全为0。。。,最后观察最后一行是否需要调整,需要就没戏了,不需要说明OK了。
举个例子,第一行的翻转方案为7:111

上述过程强烈建议手动模拟一下,其实在计算机计算时,先考虑了000的方案,然后会往后找次数更少的方案,看能否找到次数最少的方案(具体看题目要求)。
贴一下代码:
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cmath>
#include<vector>
#include<stack>
#include<map>
#include<set>
#include<list>
#include<queue>
#include<string>
#include<algorithm>
#include<iomanip>
using namespace std;
const int maxn = ;
int H[]={,-,,,};
int V[]={,,,,-};
int cur[maxn][maxn];//当前结点的颜色
int res[maxn][maxn];//最终结果
int flip[maxn][maxn];//是否翻转存放结果
int n;//行
int m;//列 bool IsIn(int x,int y)//判断是否越界
{
if(x>= && x<n && y >= && y <m)
return true;
return false;
} //查询颜色 0 或 1 | 黑 或 白
int GetStatus(int x,int y)
{
int cnt = cur[x][y];//获取当前的状态
for(int i = ;i < ;i++)
{
int x2 = x +H[i];
int y2 = y +V[i];
if(IsIn(x2,y2))
{
cnt += flip[x2][y2];//记录周围的反转次数总和
}//即周围4个加行自己5个格子的有cnt个反转过
}
return cnt % ;//最终确定自己是否需要翻转
} //对第一行的翻转进行搜索
int SolveRow1()
{
for(int i = ;i < n;i++)//第二行的翻转使第一行为0,第三行的翻转使得第二行为0,依次.
{
for(int j = ;j < m;j++)
{
if(GetStatus(i-,j))//当前为1,说明要翻转一次 为0 则不需要
{
flip[i][j] = ;//记录翻转一次
}
}
}
for(int j = ;j< m;j++)//判断最后一行
{
if(GetStatus(n-,j))//不是全0 ,即最后一行存在1 要翻转 此时没有翻转的余地了
{
return -;//返回-1
}
}
int times = ;//如果最后一行也为0,即所有的都为0了,表明第一行的翻转是可行的
for(int i = ;i <n;i++)
{
for(int j = ;j < m;j++)
{
times += flip[i][j];//记录整个矩阵的翻转总次数
}
}
return times;//返回次数
} void Solve()
{
int ans = -;
for(int i = ;i < (<<m);i++)// m列 共 2 ^ m 个选择方案 [0,2^m)
{
memset(flip,,sizeof(flip));//初始化操作
for(int j = ;j < m;j++)
{
flip[][m-j-] = i >> j & ;//1 表示要转换 0表示不动
}
int num = SolveRow1();//-1 无解
if(num >= && (ans < || ans > num))
{
ans = num;//找出最小翻转次数
memcpy(res,flip,sizeof(flip));
}
}
if(ans < )
{
cout<<"IMPOSSIBLE"<<endl;
}
else//打印翻转结果
{
for(int i = ;i < n;i++)
{
for(int j = ;j < m;j++)
{
cout<<res[i][j];
if(j!= m -)
{
cout<<" ";
}
}
cout<<endl;
}
}
} int main()
{
while(cin>>n>>m&& n!= && m!=)
{
for(int i = ;i < n;i++)
{
for(int j = ;j < m;j++)
{
cin>>cur[i][j];
}
}
Solve();
}
return ;
}
这里在对这段代码进行简单说明下
for(int i = ;i < (<<m);i++)// m列 共 2 ^ m 个选择方案 [0,2^m)
{
memset(flip,,sizeof(flip));//初始化操作
for(int j = ;j < m;j++)
{
flip[][m-j-] = i >> j & ;//1 表示要转换 0表示不动
}
.. .
...
}
其中i表示从0到2^m次方的所有的翻转方案,就把m看成3把。flip[i][j]表明第i行第j列是否要翻转,所以第一行有2^3==8中翻转方案

在对解题做个简要说明,POJ1222规模确定,确保可行,直接做即可。POJ3279也十分类似
对于1753,分别需要计算全部翻为白色的最少翻转次数和全部翻为黑色的最少翻转次数。其实只要将输入的b和w对应的1 和 0 调换下,两次始终求解将1 全部换成0的方案数,最终取最小值即可。
POJ1222、POJ3279、POJ1753--Flip的更多相关文章
- 二进制枚举例题|poj1222,poj3279,poj1753
poj1222,poj3279,poj1753 听说还有 POJ1681-画家问题 POJ1166-拨钟问题 POJ1054-讨厌的青蛙
- java.nio.ByteBuffer中flip、rewind、clear方法的区别
对缓冲区的读写操作首先要知道缓冲区的下限.上限和当前位置.下面这些变量的值对Buffer类中的某些操作有着至关重要的作用: limit:所有对Buffer读写操作都会以limit变量的值作为上限. p ...
- java.nio.ByteBuffer中的flip()、rewind()、compact()等方法的使用和区别
java.nio.ByteBuffer 1. ByteBuffer中的参数position.limit.capacity.mark含义: position:表示当前指针的位置(下一个要操作的数据元素的 ...
- NIO-java.nio.ByteBuffer中flip、rewind、clear方法的区别
Java NIO中的Buffer用于和NIO通道进行交互.如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的. 缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存.这块内存被包装成NIO ...
- Mina、Netty、Twisted一起学(八):HTTP服务器
HTTP协议应该是目前使用最多的应用层协议了,用浏览器打开一个网站就是使用HTTP协议进行数据传输. HTTP协议也是基于TCP协议,所以也有服务器和客户端.HTTP客户端一般是浏览器,当然还有可能是 ...
- JAVA NIO简介-- Buffer、Channel、Charset 、直接缓冲区、分散和聚集、文件锁
IO 是主存和外部设备 ( 硬盘.终端和网络等 ) 拷贝数据的过程. IO 是操作系统的底层功能实现,底层通过 I/O 指令进行完成. Java标准io回顾 在Java1.4之前的I/O系统中,提供 ...
- Mina、Netty、Twisted一起学(五):整合protobuf
protobuf是谷歌的Protocol Buffers的简称,用于结构化数据和字节码之间互相转换(序列化.反序列化),一般应用于网络传输,可支持多种编程语言. protobuf如何使用这里不再介绍, ...
- Android-Universal-Image-Loader三大组件DisplayImageOptions、ImageLoader、ImageLoaderConfiguration详解
一.介绍 Android-Universal-Image-Loader是一个开源的UI组件程序,该项目的目的是提供一个可重复使用的仪器为异步图像加载,缓存和显示.所以,如果你的程序里需要这个功能的话, ...
- Mina、Netty、Twisted一起学(四):定制自己的协议
在前面的博文中,介绍一些消息分割的方案,以及MINA.Netty.Twisted针对这些方案提供的相关API.例如MINA的TextLineCodecFactory.PrefixedStringCod ...
随机推荐
- 方法不会等待Task执行完才返回数据
- pytorch求范数函数——torch.norm
torch.norm(input, p='fro', dim=None, keepdim=False, out=None, dtype=None) 返回所给tensor的矩阵范数或向量范数 参数: i ...
- *438. Find All Anagrams in a String 找到字符串中所有字母异位词
1. 原始题目 给定一个字符串 s 和一个非空字符串 p,找到 s 中所有是 p 的字母异位词的子串,返回这些子串的起始索引. 字符串只包含小写英文字母,并且字符串 s 和 p 的长度都不超过 201 ...
- 报错:Connection to node -1 could not be established. Broker may not be available. (org.apache.kafka.clients.NetworkClient)
报错背景: 启动kafka消费者之后出现这种报错,持续打印相同信息. 报错现象: [root@master kafka_2.-]# /opt/kafka/kafka_2.-/bin/kafka-con ...
- Slf4j与log4j及log4j2、logbak的关系及使用方法
Slf4j与log4j及log4j2的关系及使用方法 slf4j slf4j仅仅是一个为Java程序提供日志输出的统一接口,并不是一个具体的日志实现方案,就比如JDBC一样,只是一种规则而已,所以单独 ...
- 前端研究CSS之文字与特殊符号元素结合的浏览器兼容性总结
页面布局里总是会有类似 “文字 | 文字” 的设计样式,不同的浏览器存在严重偏差. 有兼容问题就要解决,下面总结了3种解决方案,分享给大家: 一.系统默认的样式 1.元素换行的段落 <div c ...
- Django 之redis的应用
redis概述 redis是一种nosql数据库,他的数据是保存在内存中,同时redis可以定时把内存数据同步到磁盘,即可以将数据持久化,并且他比memcached支持更多的数据结构(string,l ...
- 热力图heatmap使用
参考:https://www.cnblogs.com/julinhuitianxia/p/7755246.html 1.首先到echarts官网下载应用实例:http://echarts.baidu. ...
- Beta冲刺(4/4)
队名:秃头小队 组长博客 作业博客 组长徐俊杰 过去两天完成的任务:学习了很多东西 Github签入记录 接下来的计划:继续学习 还剩下哪些任务:细节处理 燃尽图 遇到的困难:自己太菜了 收获和疑问: ...
- 按键板的原理与实现 扩展GPIO
在系统可用的GPIO口数量有限的情况下实现按键板的另一个选择就是:扩展GPIO口.扩展GPIO的方法有很多,市场上已经有很多种类的GPIO口扩展器件,但是从成本上考虑,但它们总是显得昂贵.对于按键板的 ...