昨天晚上12点刷到的这个题,一开始一位是BFS,但是一直没有思路。后来推了一下发现只需要依次枚举第一行的所有翻转状态然后再对每个情况的其它田地翻转进行暴力dfs就可以,但是由于二进制压缩学的不是很透,一直有小问题,下面我还会讲子集生成的相关方法,有兴趣的同学可以继续关注。

  本题大意:一块地,有黑(1)白(0)之分,牛每次踩踏使得当前块以及四连块都变色,问当牛如何踩时使得地都变白并且求出最小踩踏次数和踩踏路径的最小字典序时的踩踏地图。

  本题思路:由于同一块地被翻两次都会回到原来的状态,所以只需要对应每块地看他上方的地是否为黑色,为黑色则翻否则看其他情况,由于第一排的黑色只有第二排能翻,所以需要先对第一排进行枚举,然后再对其剩余的状态进行搜索即可。那么如何判断某块地是否为黑色呢,这里我们采用二进制压缩,大意就是从1 -(1 << n) 的所有数字即逆序枚举了所有状态,然后访问每个状态,如果此地上方的为白色地则跳过,黑色地则进行翻转。具体如下图所示。

  首先我们假设有m == 4列,则它所对应的数字如下图所示。

每个数对应的二进制码位如果为1则翻转,否则不翻转。

  参考代码:

 #include <cstdio>
#include <cstring>
using namespace std; const int maxn = + , INF = 0x3f3f3f;
int n, m, minx = INF;
int maze[maxn][maxn], temp[maxn][maxn], vis[maxn][maxn], ans[maxn][maxn];
int dx[] = {, , -, }, dy[] = {, , , -}; void reverse(int u, int v) {
vis[u][v] = ;
temp[u][v] = !temp[u][v];
for(int p = ; p < ; p ++) {
int ni = u + dx[p], nj = v + dy[p];
if(ni >= && nj >= && ni < n && nj < m)
temp[ni][nj] = !temp[ni][nj];
}
} bool Judge() {
for(int i = ; i < n; i ++)
for(int j = ; j < m; j ++)
if(temp[i][j] == ) return false;
return true;
} void solve(int x) {
memcpy(temp, maze, sizeof(maze));
memset(vis, , sizeof(vis));
int cnt = ;
for(int i = ; i < m; i ++) {
if((x >> i) & ) {
cnt ++;
reverse(, i);
}
}
for(int i = ; i < n; i ++) {
for(int j = ; j < m; j ++) {
if(temp[i - ][j] == ) {
reverse(i, j);
cnt ++;
}
}
}
if(Judge() && cnt < minx) {
minx = cnt;
memcpy(ans, vis, sizeof(vis));
}
} int main () {
scanf("%d %d", &n, &m);
for(int i = ; i < n; i ++)
for(int j = ; j < m; j++)
scanf("%d", &maze[i][j]);
for(int i = ; i < ( << m); i ++)
solve(i);
if(minx == INF)
printf("IMPOSSIBLE\n");
else {
for(int i = ; i < n; i ++) {
for(int j = ; j < m - ; j ++) {
printf("%d ", ans[i][j]);
}
printf("%d\n", ans[i][m - ]);
}
}
return ;
}

View Cod

POJ-3279.Fliptile(二进制状态压缩 + dfs) 子集生成的更多相关文章

  1. POJ 3279 Fliptile[二进制状压DP]

    题目链接[http://poj.org/problem?id=3279] 题意:给出一个大小为M*N(1 ≤ M ≤ 15; 1 ≤ N ≤ 15) 的图,图中每个格子代表一个灯泡,mp[i][j] ...

  2. poj 3279 Fliptile(二进制)

    http://poj.org/problem?id=3279 在n*N的矩阵上,0代表白色,1代表黑色,每次选取一个点可以其颜色换过来,即白色变成黑色,黑色变成白色,而且其上下左右的点颜色也要交换,求 ...

  3. POJ 3279 Fliptile (二进制枚举)

    <题目链接> <转载于 >>> > 题目大意: 给定一个M*N矩阵,有些是黑色(1表示)否则白色(0表示),每翻转一个(i,j),会使得它和它周围4个格变为另 ...

  4. poj 3279 Fliptile(二进制搜索)

    Farmer John knows that an intellectually satisfied cow is a happy cow who will give more milk. He ha ...

  5. 状态压缩+枚举 POJ 3279 Fliptile

    题目传送门 /* 题意:问最少翻转几次使得棋子都变白,输出翻转的位置 状态压缩+枚举:和之前UVA_11464差不多,枚举第一行,可以从上一行的状态知道当前是否必须翻转 */ #include < ...

  6. UVA 1508 - Equipment 状态压缩 枚举子集 dfs

    UVA 1508 - Equipment 状态压缩 枚举子集 dfs ACM 题目地址:option=com_onlinejudge&Itemid=8&category=457& ...

  7. POJ.3279 Fliptile (搜索+二进制枚举+开关问题)

    POJ.3279 Fliptile (搜索+二进制枚举+开关问题) 题意分析 题意大概就是给出一个map,由01组成,每次可以选取按其中某一个位置,按此位置之后,此位置及其直接相连(上下左右)的位置( ...

  8. POJ 2777.Count Color-线段树(区间染色+区间查询颜色数量二进制状态压缩)-若干年之前的一道题目。。。

    Count Color Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 53312   Accepted: 16050 Des ...

  9. POJ 3279 Fliptile(翻格子)

    POJ 3279 Fliptile(翻格子) Time Limit: 2000MS    Memory Limit: 65536K Description - 题目描述 Farmer John kno ...

随机推荐

  1. API / DOM

    浏览器特性 当控制台报错时,IE9会停止执行JS.当打开控制台时会执行后续JS ------------------------------------------------------------ ...

  2. JAVA版开源微信管家—JeeWx捷微3.1小程序版本发布,支持微信公众号,微信企业号,支付窗

    支持小程序,JeeWx捷微3.1小程序版本发布^_^ JeeWx捷微V3.1--多触点小程序版本管理平台(支持微信公众号,微信企业号,支付窗) JeeWx捷微V3.1.0版本紧跟微信小程序更新,在原有 ...

  3. css样式表2

    <head> <style type="text/css"> .main { height:42px; width:100%; text-align:cen ...

  4. confusing c++ 重写 与 重定义 记录1

    class parent { public: void f() { cout << "parent f()" << endl; } void f(int i ...

  5. Delphi 修改本地日期和时间

    procedure TForm1.ModifySysdate(D: Double); var systemtime:Tsystemtime; DateTime:TDateTime; begin Set ...

  6. linux终端发送邮件

    使用mail: echo "This is message to send" | mail -a /tmp/attachment.txt -s "This is Subj ...

  7. leetcode ex3 找出穿过最多点的直线 Max Points on a Line

    题目 https://oj.leetcode.com/problems/max-points-on-a-line/ 答案与分析 http://www.aiweibang.com/yuedu/18326 ...

  8. PHP常量总结

    概念 常量我们可以理解为值不变的量.常量只要被定义了,在程序脚本的其他任何地方都不能改变. 因为常量被定义后不能被修改,所以即使重定义常量的值,常量的值也是第一次定义常量时的值 常量不管在哪里被定义, ...

  9. Android DevArt5:如何在Android中创建多线程?

    本篇内容: 如何在Android中创建多进程?查看进程的三种方式有哪些? 多进程模式的运行机制?- 演示了多进程出现问题中的两种情况: 静态成员失效 Application多次创建 IPC基础概念介绍 ...

  10. tf.Variable和tensor的区别(转)

    刷课过程中思考到Variable和Tensor之间的区别,尝试发现在如下代码中: a = tf.Variable(tf.ones(1)) b = tf.add(a,tf.ones(1)) 1 2 a是 ...