Fliptile(翻格子问题)
题目大意:
就是给定一个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(翻格子问题)相关推荐
- bzoj 1647: [Usaco2007 Open]Fliptile 翻格子游戏(枚举)
1647: [Usaco2007 Open]Fliptile 翻格子游戏 Time Limit: 5 Sec Memory Limit: 64 MB Submit: 727 Solved: 287 ...
- Fliptile 翻格子游戏
问题 B: [Usaco2007 Open]Fliptile 翻格子游戏 时间限制: 5 Sec 内存限制: 128 MB 题目描述 Farmer John knows that an intell ...
- Fliptile 翻格子游戏[Usaco2007 Open]
题目描述 Farmer John knows that an intellectually satisfied cow is a happy cow who will give more milk. ...
- 盛大格子客或将继开心农场之后又一疯狂游戏
<格子客>预计在2010年4月19日(周一)下午14:00对外开放封测.封测邀请码共2500枚,封测期间将送出2916个实物奖品! <格子客>是一款通过简单的翻格子进行的社交产 ...
- 拯救莫莉斯[GDOI2014]
时间限制:1s 内存限制:256MB 问题描述 莫莉斯·乔是圣域里一个叱咤风云的人物,他凭借着自身超强的经济头脑,牢牢控制了圣域的石油市场. 圣域的地图可以看成是一个n*m的矩阵.每个整数坐标 ...
- 题解 P1985 【[USACO07OPEN]翻转棋】
农夫约翰知道,聪明的奶牛可以产更多的牛奶.他为奶牛设计了一种智力游戏,名叫翻转棋. 翻转棋可以分成 M × N 个格子,每个格子有两种颜色,一面是黑的,一面是白的. 一旦翻转某个格子,这个格子的颜色就 ...
- VB小游戏设计(一):扫雷
感谢VB吧@yjtx256,我的程序根据他公开的源代码改编而来 工程文件下载链接: 文件分享 提醒: 文章写得很烂,新手没必要按照博文里的描述来自己写,建议直接下载原工 ...
- Dungelot游戏思考
目标:关卡模式,在每一关找到钥匙打开门进入下一关,一关一关让自己变得更强,走的更远. 规则:游戏由5*6的格子组成地图,玩家点击每个格子,可能翻出怪物.道具.装备和NPC.再通过点击可与怪物进行交战, ...
- NOIP大纲整理:(十六)反转问题与弹性碰撞
一.反转问题 算法概览:给定一个01串,现有翻转规则:翻转某一个位置时其后面2个位置也会跟着翻转,也就是每次翻转都会翻转3个连续的位置.要将01串全部翻转为0,求最小的翻转次数.形似这类题的问题叫做反 ...
最新文章
- grep搜索当前目录和递归搜索子目录中文本文件的特定pattern
- FD.io/VPP — Overview
- python 内建比较函数详解
- The world at your fingertips — 天涯明月刀幕后24(疏离)
- oracle 匿名段,这段匿名块看着没什么问题啊
- mPaaS-RPC 拦截器各种场景下的使用指南
- ora-03113 访问某条记录_用了Excel十几年,你居然不知道“记录单”?!可能错过一个亿……...
- 数据结构(C语言版)
- Mean Rank 和Mean reciprocal rank
- 携程的旅游知识图谱构建和应用
- android设置主题背景为壁纸_Android 应用背景加载系统动态壁纸
- 解决spacedesk卸载/重装软件时显示 指定的账户已存在
- 【电子学会】2022年12月图形化一级 -- 和平使者
- 微信跳一跳刷分代码剖析
- 2020-09-15 JAVA面试题整理
- OpenCV Java入门六 使用神经网算法辩识人脸
- arcgis多个图共用一个图例_ArcGIS制图技巧,一个小技巧使图例与之匹配!
- dbd mysql db_关于DBD连接mysql数据库
- Unity之文字提示动画
- java swing实现简单KFC点餐系统