题目链接: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. 数据绑定(十)Binding的数据转换

    原文:数据绑定(十)Binding的数据转换 当Source端Path所关联的数据与Target端目标属性数据类型不一致时,需要添加数据转换器,数据转换器是一个自定义的类,这个类需要实现IValueC ...

  2. Win8Metro(C#)数字图像处理--2.19图像水平镜像

    原文:Win8Metro(C#)数字图像处理--2.19图像水平镜像  [函数名称] 图像水平镜像函数MirrorXProcess(WriteableBitmap src) [函数代码]      ...

  3. 匹配中文字符的正则表达式: [/u4e00-/u9fa5]

    原文:匹配中文字符的正则表达式: [/u4e00-/u9fa5] 这里是几个主要非英文语系字符范围(google上找到的): 2E80-33FFh:中日韩符号区.收容康熙字典部首.中日韩辅助部首.注音 ...

  4. C#高性能大容量SOCKET并发(六):超时Socket断开(守护线程)和心跳包

    原文:C#高性能大容量SOCKET并发(六):超时Socket断开(守护线程)和心跳包 守护线程 在服务端版Socket编程需要处理长时间没有发送数据的Socket,需要在超时多长时间后断开连接,我们 ...

  5. ArrayList(1.8)

    public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess ...

  6. SQL 时间格式化函数发布

    SQL 时间格式化函数,有时候因某种需要需要格式化成需要的时间格式,需要的朋友可以收藏下,以备后用. SQL Server里面可能经常会用到的日期格式转换方法: sql server使用convert ...

  7. Delphi&C#代码模拟“显示桌面”的功能(使用CreateOleObject('Shell.Application'))

    今天有人问我:“用shell打开文件(显示桌面.scf)的方式还是用模拟键盘(Win+D)显示桌面”这应该有更好的方法,就搜了搜,关键字定位“ToggleDesktop”因为显示桌面.scf的内容是: ...

  8. QT_NO_CAST_FROM_ASCII这个宏的,禁用一切来自双引号字符串字面量传入QString(有2种解决方法)

    这两天制作了两个Qt Creator增强套装的两个插件,其实也是非常简单的,但是其实花了我超过四天的时间,为什么呢?因为我之前很长一段时间都是在Linux下开发的,一切安好,没有任何问题,但是到了Wi ...

  9. U盘免疫

    界面如下: 关键部分代码如下: void CImmunityUDlg::OnBnClickedButtonOk() { // TODO: 在此添加控件通知处理程序代码 TCHAR szPath[MAX ...

  10. Django 常用模块导入记忆

    1. urls相关操作 from django.urls import path, re_path, include from django.urls import reverse // 注意reve ...