【POJ 3279 Fliptile】开关问题,模拟
题目链接:http://poj.org/problem?id=3279
题意:给定一个n*m的坐标方格,每个位置为黑色或白色。现有如下翻转规则:每翻转一个位置的颜色,与其四连通的位置都会被翻转,但注意只扩散一圈,不是连锁反应。
求最少翻转几个位置能够使所有n*m个位置都变为白色。若有解,求字典序最小的翻转方案(给出每个位置的翻转次数)。
数据范围:n, m 属于 [1, 15]
思路:我们把翻转方案中的翻转称为“主动翻转”,翻转过程中受邻居影响而发生的翻转称为“被动翻转”。观察例子可得出如下几个结论:
1. 最优解中,每个位置的主动翻转不超过1次。
2. 各个位置翻转的次序对结果没有影响。
3. 某一时刻,位置(i, j)的颜色取决于到目前为止它的主动翻转和被动翻转次数之和,记为cnt;具体地,由结论1可推得cnt为奇数则变色,偶数则不变色。
4. 位置(i, j)的被动翻转次数 = 与它四连通的位置的主动翻转次数之和。
解法:首先枚举第一行的所有可能的翻转动作,这里由于m <= 15,所以用一个整型实现“状态压缩”,即枚举所有 i 属于[0, 2m-1], i 的二进制展开的第 j 位代表原图第一行第 j 个位置是否主动翻转。
然后,由结论2、3,可对每个第一行的枚举值从第二行开始自上而下逐行递推:第 i-1 行通过第 i 行垂直位置的主动翻转而“修正”;具体地,对于位置(i, j),考查位置(i-1, j),若(i-1, j)为黑色,则目前一定要对(i, j)主动翻转才能带动(i-1, j)被动翻转为白色。这样的修正持续到最后一行,由于没有下一行可以修正最后一行,因此可直接判最后一行是否为全白,若不是则无解。
最后,对于最优解的维护,这里用二维数组b直接记录每个位置进行的主动翻转的次数。由结论3、4,可以通过数组b在O(1)时间内算出当前某个位置的颜色,以便判断是否需要修正。
解法和代码参照了http://blog.csdn.net/ac_hell/article/details/51077271 以及 http://blog.csdn.net/ac_hell/article/details/51077320,写得很清楚,学习了。
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAX_N = ;
const int MAX_M = ;
const int INF = 0x7fffffff;
int a[MAX_N][MAX_M];//原图
int b[MAX_N][MAX_M];//此位置共翻转了几次
int c[MAX_N][MAX_M];//最优解
int n, m;
int dx[] = {, , , , -}, dy[] = {, -, , , }; bool out(int x, int y){
if(x < || x >=n || y < || y >= m) return true;
return false;
} int get_color(int x, int y){
int color = a[x][y];
for(int i=; i<; i++){
int nx = x + dx[i], ny = y + dy[i];
if(out(nx, ny)) continue;
color += b[nx][ny];//主动+被动
}
return color & ;
} int flip(int s){
for(int i=; i<=m; i++){
b[][i-] = (s>>(m-i)) & ;
//printf("%d ", b[0][i-1]);
}
for(int i=; i<n; i++){
for(int j=; j<m; j++){//(i-1, j)想变,必须让(i, j)翻转
if(get_color(i-, j)){
b[i][j] = ;
//printf("%d, %d\n", i, j);
}
}
}
for(int i=; i<m; i++){
if(get_color(n-, i)){
//printf("%d no\n", i);
return INF;
} }
int times = ;
for(int i=; i<n; i++){
for(int j=; j<m; j++){
times += b[i][j];
}
}
return times;
} int main()
{
freopen("3279.txt", "r", stdin);
scanf("%d%d", &n, &m);
for(int i=; i<n; i++){
for(int j=; j<m; j++){
scanf("%d", &a[i][j]);
}
}
int ans = INF;
for(int i=; i< (<<m); i++){//信号量集
memset(b, , sizeof(b));//翻转方案
int t = flip(i);
if(t < ans){
ans = t;
memcpy(c, b, sizeof(b));//更新最优解
}
}
if(ans == INF) printf("IMPOSSIBLE\n");
else{
for(int i=; i<n; i++){
for(int j=; j<m; j++){
printf("%d ", c[i][j]);
}
printf("\n");
}
}
return ;
}
本来是做今天的计蒜之道的热身赛A题,与这道同类型。比赛时不会,然而比赛结束后已不能提交。。。
【POJ 3279 Fliptile】开关问题,模拟的更多相关文章
- POJ.3279 Fliptile (搜索+二进制枚举+开关问题)
POJ.3279 Fliptile (搜索+二进制枚举+开关问题) 题意分析 题意大概就是给出一个map,由01组成,每次可以选取按其中某一个位置,按此位置之后,此位置及其直接相连(上下左右)的位置( ...
- 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)题解
以防万一,题目原文和链接均附在文末.那么先是题目分析: [一句话题意] 给定长宽的黑白棋棋盘摆满棋子,每次操作可以反转一个位置和其上下左右共五个位置的棋子的颜色,求要使用最少翻转次数将所有棋子反转为黑 ...
- Fliptile POJ - 3279 (开关问题)
Fliptile Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 16483 Accepted: 6017 Descrip ...
- POJ 3279 Fliptile ( 开关问题)
题目链接 Description Farmer John knows that an intellectually satisfied cow is a happy cow who will give ...
- POJ - 3279 Fliptile(反转---开关问题)
题意:有一个M*N的网格,有黑有白,反转使全部变为白色,求最小反转步数情况下的每个格子的反转次数,若最小步数有多个,则输出字典序最小的情况.解不存在,输出IMPOSSIBLE. 分析: 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 (简单搜索)
Fliptile Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 16558 Accepted: 6056 Descrip ...
随机推荐
- poj 1149 pigs(最大流)
题目大意:迈克在农场工作,农场有 m 个猪舍,每个猪舍有若干只猪,但是迈克不能打开任何一间猪舍.有 n 个顾客前来购买,每个顾客有最大的购买数量,每个顾客可以购买某些猪舍的猪,且顾客可以打开这些猪舍, ...
- Linux 挂载光驱
Linux的硬件设备都在/dev目录下,/dev/cdrom表示光驱,挂载方法如下: 1.挂载光驱 [root@oracle ~]# mount -t iso9660 /dev/cdrom /mnt/ ...
- codeforces 166C Median - from lanshui_Yang
C. Median time limit per test 2 seconds memory limit per test 256 megabytes input standard input out ...
- java与.net比较学习系列(6) 数组
这一篇文章要总结的内容是数组,数组可以简单地看成是同种数据类型变量的集合,它在我们的开发中经常用到,我们主要从以下几个方面进行总结: 1,数组的创建和初始化 2,数组的访问和遍历 3,数组的总结 数组 ...
- 期望dp-hdu-4336-Card Collector
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4336 题目大意: 有n种卡片,每包中至多有一种卡片,概率分别为p1,p2,...pn,可能有的没有卡 ...
- PHP <<EOF EOF的使用方法
PHP <<EOF EOF的使用方法 <?php $name = '浅水游'; print <<<EOT <html& ...
- react-native使用react-art制作SVG动画
想要使用SVG做一个动画,郁闷了一上午终于有了一点思路.. 其实我是看了一篇国外的文章.网址:http://browniefed.com/blog/2015/05/03/getting-react-a ...
- MVC 数据列表显示插件大全
Jgrid 官网示例: http://www.trirand.net/demo/aspnet/mvc/jqgrid/ Code Project示例: http://www.codeproject.co ...
- iOS系统相册的有关操作
iOS中,我们选择相册中的资源和调用摄像头可以使用 :UIImagePickerController类来完成,不使用UI我们可以通过:ALAssetsLibrary类来使用相册资源. 一. ALAss ...
- VisualStudio2013快捷键
visual studio 2013 是一个基本完整的开发工具集,它包括了整个软件生命周期中所需要的大部分工具,如UML工具.代码管控工具.集成开发环境(IDE)等等.VS 2013 中新增了很多提高 ...