kuangbin专题 专题一 简单搜索 Fliptile POJ - 3279
题目链接:https://vjudge.net/problem/POJ-3279
题意:格子有两面,1表示黑色格子,0表示白色格子,奶牛每次可以踩一个格子,踩到的格子和它周围的上下左右格子都会翻面,也即是颜色改变,
问:能不能踩有限个格子,使得所有格子都变成白色,如果能,求踩格子次数的方案,并且要求字典序(1)最小的那一个方案。
(1):字典序,可以百度一下哦。
思路:
纯暴力枚举:
M * N个格子,每个格子翻和不翻2种可能,时间复杂度O(2^M * N),显然不行。
改进的暴力方法:
我们想:一个格子的状态取决于本身的颜色加上本身翻与不翻和四周的四个格子翻与不翻,
再想,为了让上面的思考实现而且有条理,不如我们从第一行开始判断,直到最后一行,如果
全部是白色,说明该方法可以,否则不行。
那我们可以枚举第一行的所有翻与不翻的情况,假设一行有M个格子,那么第一行的情况有2^M,
,按照第一行的颜色情况,判断第二行每个格子翻与不翻使得第一行全部变成白色,。。。以此
类推,直到最后一行。
那时间复杂度差不多是O(M * N *2^M),M∈[1,15],可行。
那具体怎么做呢,
我们需要三个数组
mp[N][N]表示原来的格子情况
cur[N][N]表示当前每个格子翻与不翻的情况,1表示翻
ans[N][N]表示最后01矩阵的符合题目的答案
一个min_t记录最小翻转次数
一个tmp_t,某个方法的当前翻转次数
其实,一个棋子翻与不翻,我们就是为了改变它上面那一个格子的状态,那它上面那个格子的状态怎么确定呢,上面说了,那我们可以这么判断:上面那一个格子的颜色加上自身翻与不翻和上左右翻与不翻的情况,于是我们可以确定上面那一个格子的状态,于是我们就可以判断该格子也就是下面那个格子翻与不翻来把上面的格子变白色,每个格子都这么做,那么题目就变得简单了。
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std; #define inf (1LL << 31) - 1
#define rep(i,j,k) for(int i = (j); i <= (k); i++)
#define rep_(i,j,k) for(int i = (j); i < (k); i++)
#define per(i,j,k) for(int i = (j); i >= (k); i--)
#define per_(i,j,k) for(int i = (j); i > (k); i--) const int N = ;
int mv_x[] = { , , , - };
int mv_y[] = { , -, , };
int ans[N][N];
int cur[N][N]; //记录的是翻与不翻的情况
int mp[N][N];
int min_t;
int tmp_t;
int n, m; inline void input(){
rep_(i, , n)rep_(j, , m){
cin >> mp[i][j];
}
} inline bool ok(int x,int y){
return (x >= && x < n && y >= && y < m);
} int search(int x, int y){
int k = mp[x][y]; //上面格子的颜色(1) rep(p, , ){ //上面格子自身和上左右的翻与不翻情况(2)
int dx = x + mv_x[p];
int dy = y + mv_y[p]; if (ok(dx, dy)){ //在地图界限内
k += cur[dx][dy];
}
} //如果(1) + (2) 为奇数说明上个格子为黑色返回1,否则是白色返回0
return k & ;
} void work(){ rep_(i, , n){
rep_(j, , m){
if (search(i - , j)){ //上个格子的情况
//上个格子是黑色
tmp_t++; //该格子翻转,使得上的格子变白色
cur[i][j] = ; //记录该格子的翻转情况
}
}
} //对最后一行检查,是否都是白色,不是直接结束该情况分支
rep_(j, , m){
if (search(n - , j)) return;
} //记录最优解
//我们枚举第一行的情况,且从000000000000000开始枚举
//那么每一个新的翻转次数一定是该反转次数字典序最小的
if (tmp_t < min_t){
min_t = tmp_t;
memcpy(ans, cur, sizeof(cur));
}
} //输出答案
inline void get_ans(){ if (min_t == inf){
cout << "IMPOSSIBLE" << endl;
return;
} rep_(i, , n){
cout << ans[i][];
rep_(j, , m) cout << " " << ans[i][j];
cout << endl;
}
} int main(){ ios::sync_with_stdio(false);
cin.tie(); cin >> n >> m; input(); //读取数据 min_t = inf;
// cout << min_t << endl;
rep_(i, , 1LL << m){ //第一行有 2^M种情况 tmp_t = ; //每种情况的次数初始化
memset(cur, , sizeof(cur)); //每种情况初始化 rep_(j, , m){
int t = (i >> j) & ; //二进制枚举第一行翻与不翻情况
//比如一行有15个格子就是2^15种情况
//000000000000000
//可以表示0~2^15 - 1,就是2^15种情况
//每一位0或者1表示翻与不翻 cur[][m - - j] = t; //每一位对1来与(&),然后记录 if (t) tmp_t++; //如果t是1,那就是第一行某个格子翻
} work();
}
get_ans(); return ;
}
kuangbin专题 专题一 简单搜索 Fliptile POJ - 3279的更多相关文章
- kuangbin专题 专题一 简单搜索 Pots POJ - 3414
题目链接:https://vjudge.net/problem/POJ-3414 题意:给你两个杯子,分别容量为A(1),B(2)和一个C,C是需要经过下列操作,得到的一个升数.(1) FILL(i) ...
- kuangbin专题总结一 简单搜索
A - 棋盘问题:在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有 ...
- Enum:Fliptile(POJ 3279)
Fliptile 题目大意:农夫想要测牛的智商,于是他把牛带到一个黑白格子的地,专门来踩格子看他们能不能把格子踩称全白 这一题其实就是一个枚举题,只是我们只用枚举第一行就可以了,因为这一题有点像开关一 ...
- Fliptile POJ - 3279 (开关问题)
Fliptile Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 16483 Accepted: 6017 Descrip ...
- Fliptile(POJ 3279)
原题如下: Fliptile Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 16494 Accepted: 6025 D ...
- [kuangbin带你飞]专题一 简单搜索(回顾)
A - 棋盘问题 POJ - 1321 注意条件:不能每放一个棋子,就标记一行和一列,我们直接枚举每一行就可以了. AC代码: #include<iostream> #include< ...
- 简单搜索 kuangbin C D
C - Catch That Cow POJ - 3278 我心态崩了,现在来回顾很早之前写的简单搜索,好难啊,我怎么写不出来. 我开始把这个写成了dfs,还写搓了... 慢慢来吧. 这个题目很明显是 ...
- 搜索入门_简单搜索bfs dfs大杂烩
dfs题大杂烩 棋盘问题 POJ - 1321 和经典的八皇后问题一样. 给你一个棋盘,只有#区域可以放棋子,同时同一行和同一列只能有一个棋子. 问你放k个棋子有多少种方案. 很明显,这是搜索题. ...
- [kuangbin带你飞]专题一 简单搜索
ID Origin Title 454 / 1008 Problem A POJ 1321 棋盘问题 328 / 854 Problem B POJ 2251 Dungeon Ma ...
随机推荐
- jquery评分星星
<!DOCTYPE html><html><head><meta http-equiv="Content-Type" content=&q ...
- xadmin下设置“use_bootswatch = True”无效解决方法
from xadmin import viewsimport xadmin class BaseSetting(object): enable_themes=True use_bootswatch=T ...
- 原生Js监听普通dom尺寸变化
原生Js监听普通dom尺寸变化 具体做法有以下几种: 初始化项目后,轮询,反复查看 dom 尺寸是否变化,这种一听就感觉不好,开销太大. 监听元素的滚动事件,在 目标 dom 里面包裹一个同等大小的 ...
- 什么是.NET Native?
使用CoreRT将.NET Core发布为Native应用程序 - KAnts - 博客园 http://www.cnblogs.com/ants/p/8630332.html Microsoft . ...
- WebAPI增加Area以支持无限层级同名Controller
原文:WebAPI增加Area以支持无限层级同名Controller 微软的WebAPI默认实现逻辑 默认实现中不支持同名Controller,否则在访问时会报HttpError,在网上找到了各种路由 ...
- Android零基础入门第74节:Activity启动和关闭
上一期我们学习了Activity的创建和配置,当时留了一个悬念,如何才能在默认启动的Activity中打开其他新建的Activity呢?那么本期一起来学习如何启动和关闭Activity. 一.概述 经 ...
- Linux正则和grep命令
设置命令的默认参数和别名 每次都要输入 ls -l ,烦不烦,我想用 ll 来表示 ls -l, 可以,只要在 ~/.bashrc 中加上 alias ll='ls -l' ,然后运行 source ...
- 对新数据库使用 Code First
如果使用的是 Visual Studio 2010,还需要安装 Nuget 1.创建应用程序 简单起见,我们将构建一个使用 Code First 执行数据访问的基本控制台应用程序. 打开 Visual ...
- JAVA命令运行cmd命令得到的结果乱码Runtime.getRuntime().exec("");
Process process = Runtime.getRuntime().exec("cmd /c dir c:"); BufferedReader bufferedReade ...
- java多线程之多生产者-多消费者
多生产者和多消费者是线程通信的经典案例,但是和生产者-消费者相比更为复杂,而且可能会产生程序假死. public class Product { private MyStack myStack; pu ...