POJ:3279-Fliptile【状态压缩】【DFS】
经典【状态压缩】【DFS】题型
题目大意:有一个 M * N 的格子,每个格子可以翻转正反面,它们有一面是黑色,另一面是白色。黑色翻转之后变成白色,白色翻转之后则变成黑色。
游戏要做的是把所有的格子翻转为白色。不过因为牛蹄很大,所以每次翻转一个格子,与它上下左右相邻接的格子也会被翻转。
求用最小的步数完成时,每个格子的翻转次数。最小步数的解有多个时,输出字典序最小的一组;解不存在的话,则输出IMPOSSIBLE
题目样例:0表示白色,1表示黑色
1 0 0 1
0 1 1 0
0 1 1 0
1 0 0 1
题目思路:首先,同一个格子翻转两次就会恢复原状,所以多次翻转是多余的。此外,翻转的格子的集合相同的话,其次序是无关紧要的。
不妨先指定好最上面一行的翻转方法。此时,能翻转(1,1)的只剩下了(2,1),所以可以直接判断(2,1)是否需要翻转。类似的(2,1)~(2,N)都能这样判断,
如此反复下去就能确定所有格子的翻转方法,最后(M,1)~(M,N)并非全为白色,则意味着不存在可行的操作方法。
像这样,先确定第一行的翻转方式,然后可以很容易判断这样是否存在解以及解的最小步数是多少,这样将第一行的所有翻转方式都尝试一次就能求出整个问题的最小步数。这个算法中最上面
一行的翻转方式共有2^N种,复杂度为O(M * N * 2^N)
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue>
#include<iomanip>
using namespace std;
const int maxn = 16;
int M, N;
const int dx[5] = { -1,0,0,0,1 };
const int dy[5] = { 0,-1,0,1,0 };
int tile[maxn][maxn];
int opt[maxn][maxn]; //保存最优解
int flip[maxn][maxn]; //保存中间结果
//查询(x,y)的颜色
int get(int x, int y)
{
int c = tile[x][y]; //注意这里要加上原来的状态
for (int d = 0; d < 5; d++) //查询周围四个以及自己的翻转次数
{
int x2 = x + dx[d], y2 = y + dy[d];
if (0 <= x2 && x2 < M && 0 <= y2 && y2 < N)
{
c += flip[x2][y2];
}
}
return c % 2; //奇数为1,偶数为0
}
//求出第1行确定的情况下的最小操作次数
//不存在解得话,返回-1
int calc()
{
//求出从第2行开始的翻转方法
for (int i = 1; i < M; i++)
{
for (int j = 0; j < N; j++)
{
if (get(i - 1, j) != 0)
{
//如果(i- 1,j)是黑色的话,则必须翻转这个格子
flip[i][j] = 1;
}
}
}
//判断最后一行是否全白
for (int j = 0; j < N; j++)
{
//无解
if (get(M - 1, j) != 0) return -1;
}
//统计翻转次数
int res = 0;
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
{
res += flip[i][j];
}
}
return res;
}
void solve()
{
int res = -1;
//按照字典序尝试第一行的所有可能性
for (int i = 0; i < 1 << N; i++) //i表示一个二进制数,用来枚举第1行的各种不同翻法,如0001就是只翻最后一个
{
memset(flip, 0, sizeof(flip));
for (int j = 0; j < N; j++)
{
flip[0][N - j - 1] = i >> j & 1;
/*eg:0011001
①j == 0; i >> j 即0011001 & 1 -> 1
②j == 1; i >> j 即0001100 & 1 -> 0
...
每次取出最后一位,存入flip中
*/
}
int num = calc(); //num记录翻转次数
if (num >= 0 && (res < 0 || res > num)) //如果找到一种可能并且所用步数更少的话,记下这种翻法
{
res = num;
memcpy(opt, flip, sizeof(flip));
}
}
if (res < 0)
//无解
printf("IMPOSSIBLE\n");
else //最后找到的就是最少的翻法,模拟一遍,然后输出
for (int i = 0; i < M; i++)
for (int j = 0; j < N; j++)
printf("%d%c", opt[i][j], j + 1 == N ? '\n' : ' ');
}
int main()
{
cin >> M >> N;
for (int i = 0; i < M; i++) //数据输入
for (int j = 0; j < N; j++)
cin >> tile[i][j]; //0表示白色,1表示黑色
solve();
return 0;
}
POJ:3279-Fliptile【状态压缩】【DFS】的更多相关文章
- POJ 3279 Fliptile 状态压缩,思路 难度:2
http://poj.org/problem?id=3279 明显,每一位上只需要是0或者1, 遍历第一行的所有取值可能,(1<<15,时间足够)对每种取值可能: 对于第0-n-2行,因为 ...
- 状态压缩+枚举 POJ 3279 Fliptile
题目传送门 /* 题意:问最少翻转几次使得棋子都变白,输出翻转的位置 状态压缩+枚举:和之前UVA_11464差不多,枚举第一行,可以从上一行的状态知道当前是否必须翻转 */ #include < ...
- POJ 3279 Fliptile(翻格子)
POJ 3279 Fliptile(翻格子) Time Limit: 2000MS Memory Limit: 65536K Description - 题目描述 Farmer John kno ...
- poj 3311(状态压缩DP)
poj 3311(状态压缩DP) 题意:一个人送披萨从原点出发,每次不超过10个地方,每个地方可以重复走,给出这些地方之间的时间,求送完披萨回到原点的最小时间. 解析:类似TSP问题,但是每个点可以 ...
- poj 1185(状态压缩DP)
poj 1185(状态压缩DP) 题意:在一个N*M的矩阵中,‘H'表示不能放大炮,’P'表示可以放大炮,大炮能攻击到沿横向左右各两格,沿纵向上下各两格,现在要放尽可能多的大炮使得,大炮之间不能相互 ...
- poj 3254(状态压缩DP)
poj 3254(状态压缩DP) 题意:一个矩阵里有很多格子,每个格子有两种状态,可以放牧和不可以放牧,可以放牧用1表示,否则用0表示,在这块牧场放牛,要求两个相邻的方格不能同时放牛,即牛与牛不能相 ...
- POJ.3279 Fliptile (搜索+二进制枚举+开关问题)
POJ.3279 Fliptile (搜索+二进制枚举+开关问题) 题意分析 题意大概就是给出一个map,由01组成,每次可以选取按其中某一个位置,按此位置之后,此位置及其直接相连(上下左右)的位置( ...
- 【POJ 3279 Fliptile】开关问题,模拟
题目链接:http://poj.org/problem?id=3279 题意:给定一个n*m的坐标方格,每个位置为黑色或白色.现有如下翻转规则:每翻转一个位置的颜色,与其四连通的位置都会被翻转,但注意 ...
- POJ 3279(Fliptile)题解
以防万一,题目原文和链接均附在文末.那么先是题目分析: [一句话题意] 给定长宽的黑白棋棋盘摆满棋子,每次操作可以反转一个位置和其上下左右共五个位置的棋子的颜色,求要使用最少翻转次数将所有棋子反转为黑 ...
- POJ - 3279 Fliptile (枚举)
http://poj.org/problem?id=3279 题意 一个m*n的01矩阵,每次翻转(x,y),那么它上下左右以及本身就会0变1,1变0,问把矩阵变成全0的,最小需要点击多少步,并输出最 ...
随机推荐
- 通过Spring MVC 实现 Restful 风格请求⽀持
通过Spring MVC可以很方便地实现Restful风格的请求支持.Restful风格的请求是一种基于HTTP协议的轻量级的Web服务架构风格,它通过HTTP的GET.POST.PUT.DELETE ...
- 【外包杯】【报错】(表面解决实际未解决)微信小程序报错:[渲染层错误] TypeError: Cannot read property ‘$$‘ of undefined
半解不解吧,反正实现了就行 渲染层出错,滑动图片组件无法显示,(swiper是轮播图插件,因此错误应该出现在swiper渲染中) 可以这样移动,但是没有图片 我觉得是路径的问题 兄弟们,目前没有解决接 ...
- 【python】无法安装pip,报错ImportError: No module named 'pip'解决方案
命令提示符输入以下代码即可 python -m ensurepip
- ClickHouse(16)ClickHouse日志引擎Log详细解析
日志引擎系列 这些引擎是为了需要写入许多小数据量(少于一百万行)的表的场景而开发的. 这系列的引擎有: StripeLog Log TinyLog 共同属性 引擎: 数据存储在磁盘上. 写入时将数据追 ...
- 本地数据备份与FTP远程数据迁移
数据是电脑中最重要的东西.为了保证数据安全,我们经常会对数据进行备份.之前一直采用将重要数据拷贝至移动硬盘的方式实现备份,实现简单但每次都需要把所有文件拷贝一次,当文件很大时效率较低. 因此,考虑使用 ...
- kotlin+springboot入门级别教程,教你如何用kotlin和springboot搭建http
先打开idea,或者用springboot官网.阿里云那边都行 然后点击新建项目,spring Initializr,我们都知道,springboot是支持kotlin的,除非你是kotlin1.3之 ...
- 微服务项目-小Q视频网
1.后台管理系统(更新中...) (1)讲师列表 (2)添加讲师 (3)导入课程分类 (4)课程分类列表 其他功能就不一一截图了,后台详细功能如下 2.前台会员系统(更新中...) (1)前台的技术栈 ...
- 【Datahub系列教程】Datahub入门必学——DatahubCLI之Docker命令详解
大家好,我是独孤风,今天的元数据管理平台Datahub的系列教程,我们来聊一下Datahub CLI.也就是Datahub的客户端. 我们在安装和使用Datahub 的过程中遇到了很多问题. 如何安装 ...
- springboot去除内嵌tomcat
springboot去除内嵌tomcat步骤 在pom文件中加入以下代码 点击查看代码 <!-- 多模块排除内置tomcat --> <dependency> <grou ...
- ElasticSearch之Delete index API
删除指定的索引. 同时删除索引关联的数据.分片.元数据等相关的资源,因此执行前需要慎重. 命令样例如下: curl -X DELETE "https://localhost:9200/tes ...