POJ 1753 位运算+枚举
题意:
给出4*4的棋盘,只有黑棋和白棋,问你最少几步可以使棋子的颜色一样。
游戏规则是:如果翻动一个棋子,则该棋子上下左右的棋子也会翻一面,棋子正反面颜色相反。
思路:
都是暴搜枚举。
第一种方法:暴力dfs枚举
棋子只有最多翻一次,因为翻两次后结果和不翻是一样的,所以整个棋盘最多翻16次。
用step代表翻转的次数,当翻转了step次时,就看一下整个棋盘是否是清一色的。
当棋盘是清一色的时候就直接输出step,得到的就是最少翻转次数使棋盘清一色。
第二种方法:利用位运算来优化
因为棋子不是白就是黑,所以可以用0和1来表示。
然后为每一个棋子编号,并计算出该棋子若翻转会影响到的棋子的位置,可以把它们都看成是二进制的。
例如 棋子位置是 第二行第二列 则翻转该棋子会影响到的棋子位置是
0 0 0 0 0 1 0 0
0 1 0 0 1 0 1 0
0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0
二进制表示 0000 0100 0000 0000 0100 1010 0100 0000
当计算最小值时可以预处理一下,即计算出由全白到该方案最少需要步数以及全黑到该方案需要的最少步数。
然后每一种方案都可以通过枚举 dp[j] = min(dp[j], dp[i]+1)来得到,dp[i]表示左上的状态,dp[j]表示右上的状态。
j = 影响的棋子位置^i
再优化之:其实
,所以用dp[(1<<16-1)^i]得到的状态j即是状态i到全黑的最少步数, 这样就可以减少一个数组的开销了。
第三种方法:利用棋子翻转的奇偶次数
预处理时计算出改变该棋子会影响的棋子位置
然后得到棋盘状态的二进制形式记做p
然后枚举翻棋子的情况,总共有2^16-1种,看一看如果翻这些牌并且改变了相应受影响位置的牌棋盘后会不会变成清一色
并记录最少的步数

Tips:
位运算的优先级比较小,所以应该st应该= (1<<16)-1,而不是1<<16-1
Code:
#include <stdio.h>
#include <cstring> int dir[][] = {, , -, , , , , , , -}; bool G[][] = {false};
bool flag;
int step;
void flip(int r, int c)
{
for (int i = ; i < ; ++i) {
int rr = dir[i][]+r, cc = dir[i][]+c;
G[rr][cc] = !G[rr][cc];
}
} bool check()
{
for (int i = ; i <= ; ++i)
for (int j = ; j <= ; ++j)
if (G[i][j] != G[][]) return false;
return true;
} void dfs(int x, int y, int depth)
{
if (depth == step) {
flag = check();
return;
}
if (flag || y == ) return; flip(x, y);
if (x < )
dfs(x+, y, depth+);
else dfs(, y+, depth+); flip(x, y);
if (x < )
dfs(x+, y, depth);
else dfs(, y+, depth);
} int main()
{
//freopen("in.txt", "r", stdin);
char c;
for (int i = ; i <= ; ++i) {
for (int j = ; j <= ; ++j) {
scanf("%c", &c);
if (c == 'w') G[i][j] = true;
else G[i][j] = false;
}
getchar();
}
for (step = ; step <= ; ++step) {
dfs(, , );
if (flag) break;
}
if (flag) printf("%d\n", step);
else puts("Impossible");
return ;
}
第一种方法:暴力dfs+枚举
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
#define INF 0x1f1f1f1f int dir[][] = {, , , , , , , -, -, };
int eff[];
int dp[<<|];
const int st = (<<)-; bool check(int x, int y)
{
return x >= && x < && y >= && y < ;
} void init()
{
int tot = ;
for (int i = ; i < ; ++i) {
for (int j = ; j < ; ++j) {
int sta = ;
for (int k = ; k < ; ++k) {
int x = i+dir[k][], y = j+dir[k][];
if (check(x, y)) sta |= (<<(x*+y));///!!!
}
eff[tot++] = sta;
}
}
} void bfs()
{
for (int i = ; i <= st; ++i) {
if (dp[i] == INF) continue; ///!!!
for (int j = ; j < ; ++j) {
int sta = i^eff[j];
dp[sta] = min(dp[sta], dp[i]+);
}
}
} int main()
{
//printf("__%d\n", st);
// freopen("in.txt", "r", stdin);
memset(dp, INF, sizeof(dp));
dp[] = ;
init();
bfs();
char c[];
int p = ;
for (int i = ; i < ; ++i) {
scanf("%s", c);
for (int j = ; j < ; ++j) {
if (c[j] == 'w') p ^= (<<(i*+j));
}
}
if (dp[p] == INF && dp[p^st] == INF) puts("Impossible");
else printf("%d\n", min(dp[p], dp[p^st]));
return ;
}
第二种方法:利用位运算存状态,并预处理
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std; const int INF = 0x1f1f1f1f;
const int st = (<<)-;
int dir[][] = {, , , , , , , -, -, };
int eff[]; bool check(int x, int y)
{
return x >= && x < && y >= && y < ;
} void init()
{
int tot = ;
for (int i = ; i < ; ++i) {
for (int j = ; j < ; ++j) {
int sta = ;
for (int k = ; k < ; ++k) {
int x = i+dir[k][], y = j+dir[k][];
if (check(x, y)) sta |= <<(*x+y);
}
eff[tot++] = sta;
}
}
} int main()
{
//freopen("in.txt", "r", stdin);
init();
int ans = INF;
char c[];
int p = ;
for (int i = ; i < ; ++i) {
scanf("%s", c);
for (int j = ; j < ; ++j) {
if (c[j] == 'b') p |= <<(i*+j);
}
}
for (int i = ; i <= st; ++i) {
int sum = ;
int pp = p;
for (int j = ; j < ; ++j) {
if ((<<j)&i) {
sum++;
pp ^= eff[j];///!!!
}
}
if (pp == || pp == st) ans = min(ans, sum);
}
if (ans == INF) puts("Impossible");
else printf("%d\n", ans);
return ;
}
第三种方法:利用枚举翻哪些牌
链接:http://poj.org/problem?id=1753
POJ 1753 位运算+枚举的更多相关文章
- 枚举进行位运算 枚举组合z
枚举进行位运算--枚举组合 public enum MyEnum { MyEnum1 = , //0x1 MyEnum2 = << , //0x2 MyEnum3 = << , ...
- POJ 1753. Flip Game 枚举or爆搜+位压缩,或者高斯消元法
Flip Game Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 37427 Accepted: 16288 Descr ...
- 在C#中对枚举进行位运算--枚举组合
由于枚举的基础类型类型为基本的数值类型,支持位运算,因此可以使用一个值表示多个枚举的组合,在定义枚举时需要指定枚举数为2的幂指数方便进行位运算,即枚举数为1,2,4,8…,或1,1<<1, ...
- POJ 3220 位运算+搜索
转载自:http://blog.csdn.net/lyhypacm/article/details/5813634 DES:相邻的两盏灯状态可以互换,给出初始状态.询问是否能在三步之内到达.如果能的话 ...
- poj 1222 EXTENDED LIGHTS OUT(位运算+枚举)
http://poj.org/problem?id=1222 题意:给一个确定的5*6放入矩阵.每一个格子都有一个开关和一盏灯,0表示灯没亮,1表示灯亮着.让你输出一个5*6的矩阵ans[i][j], ...
- POJ 2965 The Pilots Brothers' refrigerator 位运算枚举
The Pilots Brothers' refrigerator Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 151 ...
- poj 1753 Flip Game 枚举(bfs+状态压缩)
题目:http://poj.org/problem?id=1753 因为粗心错了好多次……,尤其是把1<<15当成了65535: 参考博客:http://www.cnblogs.com/k ...
- hdu 1882 Strange Billboard(位运算+枚举)
http://acm.hdu.edu.cn/showproblem.php?pid=1882 感觉非常不错的一道题. 给一个n*m(1<=n,m<=16)的矩阵,每一个格子都有黑白两面,当 ...
- POJ1222熄灯问题【位运算+枚举】
EXTENDED LIGHTS OUT Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 14231 Accepted: 8 ...
随机推荐
- Apache 服务器
1.介绍 Apache原来用于小型或试验性Internet网络,后来逐步扩展到各种系统中,对Linux的支持几乎完美.Apache可以支持SSL技术,支持多台虚拟主机.Apache是以进程为基础的结构 ...
- 性能测试之LoardRunner 检查点
概述 1.检查点概念 2.实例 以下是详细介绍 检查点:首先来看一下VuGen确定脚本运行成功的判断条件.在录制编写脚本后,通常就会进行回放,如果回放通过没有错误,就认为脚本是正确的.究竟VuGen怎 ...
- Servlet的学习之Session(1)
在学习完了Servlet中的Cookie技术后,我们再来学习另一个能保存会话数据的技术——Session. Session是服务器端技术,利用这个技术,服务器在运行时可以为每一个用户的浏览器创建一个其 ...
- 利用JS跨域做一个简单的页面訪问统计系统
事实上在大部分互联网web产品中,我们一般会用百度统计或者谷歌统计分析系统,通过在程序中引入特定的JS脚本,然后便能够在这些统计系统中看到自己站点页面详细的訪问情况.可是有些时候,因为一些特殊情况,我 ...
- 最完整的历史记录hadoop
课程主要涉及Hadoop Sqoop.Flume.Avro重要子项目的技术实战 课程针对人群 1.本课程适合于有一定java基础知识.对数据库和sql语句有一定了解,熟练使用linux系统的技术人员, ...
- Ajax - 异步处理(点击变成文本框并修改)
效果: 对应的文档结构: Test.aspx 前台代码: 引入JQuery(jquery-1.8.3.min.js). 引入自己所写的JS代码(UserJS.js). <html xmlns=& ...
- hdu 5183(hash)
传送门:Negative and Positive (NP) 题意:给定一个数组(a0,a1,a2,⋯an−1)和一个整数K, 请来判断一下是否存在二元组(i,j)(0≤i≤j<n)使得 NP− ...
- Swift - 解析JSON数据(内置NSJSONSerialization与第三方JSONKit)
一,使用自带的NSJSONSerialization 苹果从IOS5.0后推出了SDK自带的JSON解决方案NSJSONSerialization,这是一个非常好用的JSON生成和解析工具,效率也比其 ...
- go(一)变量
package main import ( "fmt" ) func main() { var a int a = var a1 string a1 = "my is a ...
- RSA加密前言
RSA:非对称加密,近期因为工作需要需要实现了一个RSA加密方案.查阅文档无数,主要是通过看他们代码及其引用他人的代码基本实现了跨平台的RSA方案.现在唯一的缺陷是加解密花费的时间太多,下周会把加解密 ...