题目链接: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的更多相关文章

  1. kuangbin专题 专题一 简单搜索 Pots POJ - 3414

    题目链接:https://vjudge.net/problem/POJ-3414 题意:给你两个杯子,分别容量为A(1),B(2)和一个C,C是需要经过下列操作,得到的一个升数.(1) FILL(i) ...

  2. kuangbin专题总结一 简单搜索

    A - 棋盘问题:在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有 ...

  3. Enum:Fliptile(POJ 3279)

    Fliptile 题目大意:农夫想要测牛的智商,于是他把牛带到一个黑白格子的地,专门来踩格子看他们能不能把格子踩称全白 这一题其实就是一个枚举题,只是我们只用枚举第一行就可以了,因为这一题有点像开关一 ...

  4. Fliptile POJ - 3279 (开关问题)

    Fliptile Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 16483   Accepted: 6017 Descrip ...

  5. Fliptile(POJ 3279)

    原题如下: Fliptile Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 16494   Accepted: 6025 D ...

  6. [kuangbin带你飞]专题一 简单搜索(回顾)

    A - 棋盘问题 POJ - 1321 注意条件:不能每放一个棋子,就标记一行和一列,我们直接枚举每一行就可以了. AC代码: #include<iostream> #include< ...

  7. 简单搜索 kuangbin C D

    C - Catch That Cow POJ - 3278 我心态崩了,现在来回顾很早之前写的简单搜索,好难啊,我怎么写不出来. 我开始把这个写成了dfs,还写搓了... 慢慢来吧. 这个题目很明显是 ...

  8. 搜索入门_简单搜索bfs dfs大杂烩

    dfs题大杂烩 棋盘问题  POJ - 1321 和经典的八皇后问题一样.  给你一个棋盘,只有#区域可以放棋子,同时同一行和同一列只能有一个棋子. 问你放k个棋子有多少种方案. 很明显,这是搜索题. ...

  9. [kuangbin带你飞]专题一 简单搜索

            ID Origin Title 454 / 1008 Problem A POJ 1321 棋盘问题   328 / 854 Problem B POJ 2251 Dungeon Ma ...

随机推荐

  1. js table鼠标点击时变色

    <head>    <title></title>    <script type="text/javascript">      ...

  2. 【转】 C#后台调用前台javascript的五种方法

    第一种,OnClientClick    (vs2003不支持这个方法)<asp:ButtonID="Button1" runat="server" Te ...

  3. ELINK编程器支持芯片详细列表

    支持MCU芯片包括:STM32  F0.F1.F2.F3.F4.L0.L1全系列: GD32 F10XX系列. 各系列芯片支持详情如下:

  4. Wow6432Node

    64 位版本 Windows 中的注册表分为 32 位注册表项和 64 位注册表项.许多 32 位注册表项与其相应的 64 位注册表项同名,反之亦然. 64 位版本 Windows 包含的默认 64 ...

  5. Win8Metro(C#)数字图像处理--2.29图像除法运算

    原文:Win8Metro(C#)数字图像处理--2.29图像除法运算  [函数名称] 图像除法函数DivisionProcess(WriteableBitmap src, WriteableBit ...

  6. 【转】编程之道 之 Rob Pike

    1.你无法断定程序会在什么地方耗费运行时间.瓶颈经常出现在想不到的地方,所以别急于胡乱找个地方改代码,除非你已经证实那儿就是瓶颈所在. 2.估量.在你没对代码进行估量,特别是没找到最耗时的那部分之前, ...

  7. 记一次ASP.NET MVC4 升级到MVC5的小问题解决

    原文:记一次ASP.NET MVC4 升级到MVC5的小问题解决 .NET 4.0 MVC4版本,升级到.NET 4.6.1 MVC5: 1.使用nuget更新所有 与mvc相关的类库; 2.更改~/ ...

  8. MIPS虚拟机代码

    http://download.eeworld.com.cn/download/mamselc/472333http://download.eeworld.com.cn/detail/lamas/36 ...

  9. QT延时方法整理(QTimer::singleShot,QWaitCondition,QDateTime.secsTo三种新方法)

    1: void QTimer::singleShot ( int msec, QObject * receiver, const char * member ) [static] 样例: #inclu ...

  10. MotionManager 陀螺仪实现方式

      题外话:   权利的游戏开播了,引用一句话:   布兰:一个人如果还把,他还能勇敢么?   奈德:人在害怕时候的勇敢,才是真的勇敢.     回归正题:   说下关于 CMMotionManage ...