博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
poj 3279
阅读量:5305 次
发布时间:2019-06-14

本文共 1413 字,大约阅读时间需要 4 分钟。

传送门:

题面描述:

给你一个方格,这个方格中有M*N个小方块,每个小方块都是0或1,定义一种反转操作:,每次反转范围是中心方块以及其上下左右的方块,反转后状态变化为0->1,1->0。问能不能通过有限次反转操作,将方格的最终状态变为全是0,如果可以,输出一个反转次数最少而且字典序最小的矩阵,矩阵对应的数值为该位置的反转次数,否则,输出IMPOSSIBLE。

思路:

1.对于同一个位置来说,最多反转1次,因为只有两种状态,反转两次事实上跟原先状态是一样的。

2.对于同一个位置,它的最终状态会受其上下左右各个方块反转的影响,这会使问题的分析变得非常复杂,但是我们可以先确定第一行的反转次序,此时对于第一行来说,能够影响它的左中右的反转都已经确定了,那么决定他最终状态的就只有它的下的反转,调节他下面方块的反转次序,使第一行的状态全变成0,然后对于第二行一样,以此类推,到了倒数第一行,此时不仅确定了倒数第二行的状态,也把最后一行的反转次数确定了,同时,最后一行的状态也被确定了(可能有点绕),此时我们只要判断最后一行是不是全是0就可判断这种第一行的反转次序是不是可以满足条件。

3.接下来,我们来思考如何来枚举第一行的各种反转次数,由1可以知道,每个位置事实上只有0和1两种状态,所以我们可以考虑二进制枚举来解决问题,具体实现在AC代码里面。因为我们是从小到大枚举的,所以最终得到的结果一定是最小字典序的,所以不用再考虑字典序的问题了。

最终代码:

#include 
#include
#include
using namespace std;const int maxn = 20;int map[maxn][maxn],flip[maxn][maxn],ans[maxn][maxn],m,n;int dx[] = {
1,0,0,0,-1};int dy[] = {
0,1,0,-1,0};int get(int x,int y){ int c =map[x][y]; for(int d = 0;d<5;d++){ int x1 = x+dx[d]; int y1 = y+dy[d]; if(x1>=0&&x
=0&&y
>j&1; int num = calc(); if(num>=0&&(res<0||res>num)){ res = num; memcpy(ans,flip,sizeof(flip)); } } if(res==-1) printf("IMPOSSIBLE\n"); else { for(int i = 0;i

如还有困惑的地方,请在评论区留言交流!

转载于:https://www.cnblogs.com/baihualiaoluan/p/10964444.html

你可能感兴趣的文章
Handler没法取出消息队列中的数据的一个原因
查看>>
给 C# 中的 Guid 扩展一个 TryParse 方法
查看>>
C指针-const char* p到底是什么不可以改变
查看>>
TextField 、 FTE、 TLF 的使用情景和简单说明
查看>>
第27月第28天 iOS bundle
查看>>
LeetCode Min Stack
查看>>
阿里云上传下载文件
查看>>
sublime3安装javascript控制台环境 方法1
查看>>
中位数
查看>>
升讯威微信营销系统开发实践:(2)中控服务器的详细设计( 完整开源于 Github)...
查看>>
java课程之配置jdk环境
查看>>
spring AOP 动态切换数据库 (读写库)
查看>>
Codeforces Round #379 (Div. 2) E. Anton and Tree
查看>>
二维码
查看>>
设计模式六大原则(4):接口隔离原则
查看>>
小白必须懂的MongoDB的十大总结
查看>>
Mindjump!基于微信域名检测接口的跳转系统,实现微信跳转浏览器下载app
查看>>
环境决定未来
查看>>
PostgreSQL学习手册(十四) 系统视图
查看>>
记一次centos7内核可能意外丢失(测试直接干掉)恢复方法
查看>>