hdu 1882 Strange Billboard(位运算+枚举)
http://acm.hdu.edu.cn/showproblem.php?pid=1882
感觉非常不错的一道题。
给一个n*m(1<=n,m<=16)的矩阵,每一个格子都有黑白两面,当翻一个格子时,它的上下左右都要翻转,问最后使格子全变为白色的最少翻转步数。
仅仅需枚举第一行的状态即可,由于对于第i(i>=2)行j列翻转情况受上一行的制约,仅仅有当上一行也是‘X’的时候,该行j列才干翻转,使i-1行j列变为‘.’,否则i行j列不能翻转。依次进行下去,当最后一行全变为白色,说明翻转成功。
一个非常重要的优化:当n < m时,将矩阵转置,这样状态数由 (1<<m)-1 变为 (1<<n)-1。
跑了280ms,看了其它人的博客,他应该是按行翻转的。只是那一些个位运算,搞不懂。。。
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <stack>
#include <vector>
#include <queue>
#define LL long long
#define _LL __int64
using namespace std;
const int INF = 0x3f3f3f3f; int n,m;
char map[17][17];
int sta[17],tmp[17];
int bit[17];
int ans; void cal()
{
bit[0] = 1;
for(int i = 1; i < 17; i++)
bit[i] = (bit[i-1] << 1);
} void input()
{
memset(sta,0,sizeof(sta)); //记录每一行的状态
if(n >= m)
{
for(int i = 0; i < n; i++)
{
scanf("%s",map[i]);
for(int j = 0; j < m; j++)
{
if(map[i][j] == 'X')
sta[i] = (sta[i] << 1) + 1;
else sta[i] <<= 1;
}
}
}
//优化,当m < n时矩阵转换
else
{
for(int i = 0; i < n; i++)
{
scanf("%s",map[i]);
for(int j = 0; j < m; j++)
{
if(map[i][j] == 'X')
sta[j] = (sta[j] << 1) + 1;
else sta[j] <<= 1;
}
}
swap(n,m);
}
} void solve()
{
int step;
ans = INF;
for(int i = 0; i < (1<<m); i++)
{
memcpy(tmp,sta,sizeof(sta));
step = 0;
//先找出第一行应该翻转的列并进行翻转
for(int j = 0; j < m && step < ans; j++)
{
if(bit[j]&i)
{
step++;
if(j > 0)
tmp[0] ^= bit[j-1];
if(j < m-1)
tmp[0] ^= bit[j+1];
tmp[0] ^= bit[j];
tmp[1] ^= bit[j];
}
}
//依据j-1行的状态依次翻转第j行
for(int j = 1; j < n && step < ans; j++)
{
for(int k = 0; k < m && step < ans; k++)
{
if(bit[k]&tmp[j-1])
{
step++;
if(k > 0)
tmp[j] ^= bit[k-1];
if(k < m-1)
tmp[j] ^= bit[k+1];
tmp[j] ^= bit[k];
tmp[j+1] ^= bit[k];
}
}
} if(!tmp[n-1])
ans = min(ans,step);
}
} int main()
{
cal();
while(~scanf("%d %d",&n,&m))
{
if(n == 0 && m == 0) break; input();
solve(); if(ans == INF)
printf("Damaged billboard.\n");
else printf("You have to tap %d tiles.\n",ans);
}
return 0;
}
hdu 1882 Strange Billboard(位运算+枚举)的更多相关文章
- HDU 1882 Strange Billboard(位运算)
题目链接 题意 : 给你一个矩阵,有黑有白,翻转一个块可以让上下左右都翻转过来,问最少翻转多少次能让矩阵变为全白. 思路 : 我们从第一行开始枚举要翻转的状态,最多可以枚举到2的16次方,因为你只要第 ...
- HDU 1882 Strange Billboard(状态压缩+转置优化)
状态压缩,我们枚举第一行的所有状态,然后根据第一行去转变下面的行,枚举或者深搜直到最后最后一行,可以判断是不是所有的1都可以全部转换为0,记录所有的解,输出最小的一个就可以. 这里有一个很重要的优化, ...
- 枚举进行位运算 枚举组合z
枚举进行位运算--枚举组合 public enum MyEnum { MyEnum1 = , //0x1 MyEnum2 = << , //0x2 MyEnum3 = << , ...
- POJ 1753 位运算+枚举
题意: 给出4*4的棋盘,只有黑棋和白棋,问你最少几步可以使棋子的颜色一样. 游戏规则是:如果翻动一个棋子,则该棋子上下左右的棋子也会翻一面,棋子正反面颜色相反. 思路: 都是暴搜枚举. 第一种方法: ...
- 在C#中对枚举进行位运算--枚举组合
由于枚举的基础类型类型为基本的数值类型,支持位运算,因此可以使用一个值表示多个枚举的组合,在定义枚举时需要指定枚举数为2的幂指数方便进行位运算,即枚举数为1,2,4,8…,或1,1<<1, ...
- HDU 6186 CS Course【前后缀位运算枚举/线段树】
[前后缀枚举] #include<cstdio> #include<string> #include<cstdlib> #include<cmath> ...
- poj 1222 EXTENDED LIGHTS OUT(位运算+枚举)
http://poj.org/problem?id=1222 题意:给一个确定的5*6放入矩阵.每一个格子都有一个开关和一盏灯,0表示灯没亮,1表示灯亮着.让你输出一个5*6的矩阵ans[i][j], ...
- hdu 5023 线段树+位运算
主要考线段树的区间修改和区间查询,这里有一个问题就是这么把一个区间的多种颜色上传给父亲甚至祖先节点,在这里题目告诉我们最多30颜色,那么我们可以把这30中颜色用二进制储存和传给祖先节点,二进制的每一位 ...
- POJ1222熄灯问题【位运算+枚举】
EXTENDED LIGHTS OUT Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 14231 Accepted: 8 ...
随机推荐
- C#中调用WIN32的API
最近在学习C#中的GDI部分,本来尝试编写一个字幕控件(其实还是用label比较合适),但是发现控件中用GDI将整个控件粉刷貌似不行(应该是我水平不行),所以就去捣鼓了下WIN32的DLL,发现用AP ...
- 一篇旧文章,结合汇编探索this指针
//VC6.0下成功编译 #include <iostream.h> class X{ public: void foo(int b,int c){ this->a=b*c; cou ...
- C# 关于NULL 可空值类型 ? 和空接操作符??
作者 陈嘉栋(慕容小匹夫) C#引入了可空值类型的概念.在介绍究竟应该如何使用可空值类型之前,让我们先来看看在基础类库中定义的结构--System.Nullable<T>.以下代码便是Sy ...
- SequoiaDB 架构指南
1 简介 SequoiaDB(巨杉数据库)是一款分布式非关系型文档数据库,可以被用来存取海量非关系型的数据,其底层主要基于分布式,高可用,高性能与动态数据类型设计,与当前主流分布式计算框架 Hadoo ...
- ExtJs + Struts2 + JSON
最近一直都在看EXTJS的东西,然后自己实践了下,界面倒是蛮漂亮的,但是一旦涉及到与服务器端进行数据互动麻烦就出来了,本来下了个例子确发现是 用DWR的,觉得我既然用了STRUTS2作为MVC的框架, ...
- Unity NGUI实现序列帧动画播放
如题,要实现序列帧的播放导入图片的时候需要注意: (1)图片的命名要连续,如图: (2)将这些图片在NGUI中打包成Altas图集的时候图片应该在同一个Altas中: 这里以播放特效为例,满足条件时播 ...
- HDOJ迷宫城堡(判断强连通 tarjan算法)
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission( ...
- 安装配置MongoDB
1.下载mongodb https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-2.6.8.tgz 2.解压 tar zxf mongodb-lin ...
- AndroidStudio SVN检出
版本管理是每个项目的必经之路,很多的ADT都会集成版本管理插件.AS也同样可以集成GITHUB和SVN插件.github对项目有一定的限制,而SVN就比较开放了,所以我们在用AS开发的时候一般用SVN ...
- 字符串(后缀自动机):NOI 2016 优秀的拆分
[问题描述] 如果一个字符串可以被拆分为 AABB 的形式,其中 A 和 B 是任意非空字符串, 则我们称该字符串的这种拆分是优秀的. 例如,对于字符串 aabaabaa,如果令 A = aab, B ...