题目大意:

就是给定一个m*n的矩阵代表地板砖,0代表白砖,1代表黑砖,每个砖都有两面,一面白一面黑,翻转一次即可把白变成黑把黑变成白,但与此同时,与该砖块相邻的上下左右四块转也随之翻转。要求使用最少的翻转次数,将砖块翻转。 要求输出反转位置。

思路:

这是典型的开关问题,重点是要想到第一行的格子能被第一行翻转影响,也能被第二行反转影响,所以第一行要特殊处理,二进制枚举第一行所有翻转情况,之后每一行的反转就都有唯一解了。因为剩下的过程就是:用第二行翻转来保证第一行全白,用第三行翻转来保证第二行全白......依次类推,最后检查最后一行是否都是白色,如果是就得到一个结果,否则就无解。

代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string.h>
#include <climits>
using namespace std;
const int MAXN = 17;
//五个方向
const int dirx[5] = {0, 1, -1, 0, 0};
const int diry[5] = {0, 0, 0, 1, -1};int m, n; //行数,列数
int board[MAXN][MAXN]; //初始情况
int tra[MAXN][MAXN]; //临时的翻转记录
int ans[MAXN][MAXN]; //最终结果(最终的翻转记录)//查询(x, y)的颜色
int get(int x, int y){int c = board[x][y]; //初始颜色for(int i=0; i<5; i++){int xi = x + dirx[i];int yi = y + diry[i];if(xi>=0 && xi<m && yi>=0 && yi<n){//加上所有翻转情况c += tra[xi][yi];}}return c % 2; //返回最后得到的颜色
}//求第1行确定的情况下的最少操作次数
//解不存在的话返回-1
int dfs(){//首先确定从第二行开始的翻转方法for(int i=1; i<m; i++){ //遍历行for(int j=0; j<n; j++){ //遍历列if(get(i-1, j) == 1){ //检查上一行是否为黑色,判断是否需要翻转//如果是1,需要翻转tra[i][j] = 1;}}}//然后检查最后一行是否都为白色,判断这种方法是否可行for(int j=0; j<n; j++){if(get(m-1, j) == 1) return -1; //只要有一个是黑色,就不可行}//能到达这里,说明该方法可行,那就统计翻转次数并返回int count = 0;for(int i=0; i<m; i++){for(int j=0; j<n; j++){count += tra[i][j];}}return count;
}int main(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);//输入cin >> m >> n;for(int i=0; i<m; i++){for(int j=0; j<n; j++){cin >> board[i][j];}}int res = -1;for(int i=0; i<(1<<m); i++){ //遍历第一行所有翻转情况memset(tra, 0, sizeof(tra));for(int j=0; j<n; j++){tra[0][j] = (i>>j) & 1; //记录第一行的翻转结果}int cur = dfs(); //计算当前情况的翻转次数if(cur >= 0 && (res == -1 || cur < res)){//遇到更优解,就重新记录res = cur;memcpy(ans, tra, sizeof(tra)); //把tra复制到ans中去}}if(res == -1) {cout << "IMPOSSIBLE" << endl; return 0;}else {for(int i=0; i<m; i++){for(int j=0; j<n; j++){printf("%d%c", ans[i][j], j+1 == n ? '\n' : ' ');}}}
}

Fliptile(翻格子问题)相关推荐

  1. bzoj 1647: [Usaco2007 Open]Fliptile 翻格子游戏(枚举)

    1647: [Usaco2007 Open]Fliptile 翻格子游戏 Time Limit: 5 Sec  Memory Limit: 64 MB Submit: 727  Solved: 287 ...

  2. Fliptile 翻格子游戏

    问题 B: [Usaco2007 Open]Fliptile 翻格子游戏 时间限制: 5 Sec  内存限制: 128 MB 题目描述 Farmer John knows that an intell ...

  3. Fliptile 翻格子游戏[Usaco2007 Open]

    题目描述 Farmer John knows that an intellectually satisfied cow is a happy cow who will give more milk. ...

  4. 盛大格子客或将继开心农场之后又一疯狂游戏

    <格子客>预计在2010年4月19日(周一)下午14:00对外开放封测.封测邀请码共2500枚,封测期间将送出2916个实物奖品! <格子客>是一款通过简单的翻格子进行的社交产 ...

  5. 拯救莫莉斯[GDOI2014]

    时间限制:1s     内存限制:256MB 问题描述 莫莉斯·乔是圣域里一个叱咤风云的人物,他凭借着自身超强的经济头脑,牢牢控制了圣域的石油市场. 圣域的地图可以看成是一个n*m的矩阵.每个整数坐标 ...

  6. 题解 P1985 【[USACO07OPEN]翻转棋】

    农夫约翰知道,聪明的奶牛可以产更多的牛奶.他为奶牛设计了一种智力游戏,名叫翻转棋. 翻转棋可以分成 M × N 个格子,每个格子有两种颜色,一面是黑的,一面是白的. 一旦翻转某个格子,这个格子的颜色就 ...

  7. VB小游戏设计(一):扫雷

    感谢VB吧@yjtx256,我的程序根据他公开的源代码改编而来 工程文件下载链接:         文件分享 提醒:         文章写得很烂,新手没必要按照博文里的描述来自己写,建议直接下载原工 ...

  8. Dungelot游戏思考

    目标:关卡模式,在每一关找到钥匙打开门进入下一关,一关一关让自己变得更强,走的更远. 规则:游戏由5*6的格子组成地图,玩家点击每个格子,可能翻出怪物.道具.装备和NPC.再通过点击可与怪物进行交战, ...

  9. NOIP大纲整理:(十六)反转问题与弹性碰撞

    一.反转问题 算法概览:给定一个01串,现有翻转规则:翻转某一个位置时其后面2个位置也会跟着翻转,也就是每次翻转都会翻转3个连续的位置.要将01串全部翻转为0,求最小的翻转次数.形似这类题的问题叫做反 ...

最新文章

  1. grep搜索当前目录和递归搜索子目录中文本文件的特定pattern
  2. FD.io/VPP — Overview
  3. python 内建比较函数详解
  4. The world at your fingertips — 天涯明月刀幕后24(疏离)
  5. oracle 匿名段,这段匿名块看着没什么问题啊
  6. mPaaS-RPC 拦截器各种场景下的使用指南
  7. ora-03113 访问某条记录_用了Excel十几年,你居然不知道“记录单”?!可能错过一个亿……...
  8. 数据结构(C语言版)
  9. Mean Rank 和Mean reciprocal rank
  10. 携程的旅游知识图谱构建和应用
  11. android设置主题背景为壁纸_Android 应用背景加载系统动态壁纸
  12. 解决spacedesk卸载/重装软件时显示 指定的账户已存在
  13. 【电子学会】2022年12月图形化一级 -- 和平使者
  14. 微信跳一跳刷分代码剖析
  15. 2020-09-15 JAVA面试题整理
  16. OpenCV Java入门六 使用神经网算法辩识人脸
  17. arcgis多个图共用一个图例_ArcGIS制图技巧,一个小技巧使图例与之匹配!
  18. dbd mysql db_关于DBD连接mysql数据库
  19. Unity之文字提示动画
  20. java swing实现简单KFC点餐系统

热门文章

  1. 2023基于微信小程序的婚庆婚纱摄影预约平台(SSM+mysql)-JAVA.VUE(论文+开题报告+运行)
  2. 第 3 章 判断语句
  3. JavaScript 基础篇(一)
  4. 《我也有一个梦想》林达读后感
  5. Excel使用大全(二)
  6. 流水的科技股,铁打的PS、Flash亲爹Adobe
  7. VS错误提示:C4996 解决方法
  8. 投资理财-幸福只需十万
  9. 【MATLAB】将数据保存为mat格式
  10. 行人检测(一)python+OpenCV实现