[poj]开关类问题 枚举 位运算
poj 1222 EXTENDED LIGHTS OUT
开关只有两种方案 按和不按,按两次相当于关
只用枚举第一排开关的按法即可,剩下的行为使上一排的灯全部关闭,按法可以确定,并且是唯一的。
最后检查最后一行是否都为0,都为0为可行的方案。 用位运算来实现。
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std; char ol[], l[], r[];
int t; int getBit(char c, int i)
{
return & (c>>i);
} void setBit(char &c, int i, int v)
{
if (v) {
c |= ( << i);
}
else
c &= ~( << i);
} void FlipBit(char &c, int i)
{
c ^= ( << i);
} void output()
{
cout << "PUZZLE #" << t << endl;
for (int i = ; i < ; i++) {
for (int j = ; j < ; j++) {
cout << getBit(r[i], j);
if (j < )
cout << " ";
}
cout << endl;
}
} int main()
{
//freopen("1.txt", "r", stdin);
int T;
cin >> T;
for (t = ; t <= T; t++) {
for (int i = ; i < ; i++)
for (int j = ; j < ; j++) {
int s;
cin >> s;
setBit(ol[i], j, s);
} for (int n = ; n < ; n++) { //枚举第一列方案0~2^6-1
memcpy(l, ol, sizeof(ol));
int switchs = n; //当前行的开关状态
for (int i = ; i < ; i++) {
r[i] = switchs;
for (int j = ; j < ; j++) {
if (getBit(switchs, j)) {
if (j > )
FlipBit(l[i], j-);
FlipBit(l[i], j);
if (j < )
FlipBit(l[i], j+);
}
}
if (i < )
l[i+] ^=switchs;
switchs = l[i]; //i+1行灯的状态由第i行灯的状态决定
}
if (l[] == ) {
output();
break;
}
}
} return ;
}
特殊密码锁
描述
有一种特殊的二进制密码锁,由n个相连的按钮组成(n<30),按钮有凹/凸两种状态,用手按按钮会改变其状态。
然而让人头疼的是,当你按一个按钮时,跟它相邻的两个按钮状态也会反转。当然,如果你按的是最左或者最右边的按钮,该按钮只会影响到跟它相邻的一个按钮。
当前密码锁状态已知,需要解决的问题是,你至少需要按多少次按钮,才能将密码锁转变为所期望的目标状态。
输入两行,给出两个由0、1组成的等长字符串,表示当前/目标密码锁状态,其中0代表凹,1代表凸。输出至少需要进行的按按钮操作次数,如果无法实现转变,则输出impossible。
样例输入
011
000
样例输出
1 类似的思想,枚举第一个的状态,两种可能,那剩下的就可以唯一确定了,最后检查最后一位即可
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <string>
using namespace std;
#define INF 0x3f3f3f3f
int src, des, r, t;
int ans; int getBit(int c, int i)
{
return & (c >> i);
} void setBit(int &c, int i, int v)
{
if (v)
c |= ( << i);
else
c &= ~( << i);
} void flipBit(int &c, int i)
{
c ^= ( << i);
} int main()
{
//freopen("1.txt", "r", stdin);
string a;
cin >> a;
int len = a.length();
for (int i = ; i < len; i++)
setBit(src, i, a[i]-''); cin >> a;
for (int i = ; i < len; i++)
setBit(des, i, a[i]-''); int Min, cnt;
for (int p = ; p < ; p++) {
Min = INF; cnt = ;
t = src;
if (p) {
flipBit(t, );
flipBit(t, );
cnt++;
}
for (int i = ; i < len; i++) {
if (getBit(t, i-) != getBit(des, i-)) {
cnt++;
flipBit(t, i);
if (i < len-)
flipBit(t, i+);
}
}
if (getBit(t, len-) == getBit(des, len-)) {
if (cnt < Min) {
Min = cnt;
ans = cnt;
}
}
}
if (Min == INF)
cout << "impossible";
else
cout << ans; return ;
}
poj 1166 拨钟问题
有9个时钟,排成一个3*3的矩阵。
|-------| |-------| |-------|
| | | | | | |
|---O | |---O | | O |
| | | | | |
|-------| |-------| |-------|
A B C |-------| |-------| |-------|
| | | | | |
| O | | O | | O |
| | | | | | | | |
|-------| |-------| |-------|
D E F |-------| |-------| |-------|
| | | | | |
| O | | O---| | O |
| | | | | | | |
|-------| |-------| |-------|
G H I
(图 1)
现在需要用最少的移动,将9个时钟的指针都拨到12点的位置。共允许有9种不同的移动。如下表所示,每个移动会将若干个时钟的指针沿顺时针方向拨动90度。
移动 影响的时钟 1 ABDE
2 ABC
3 BCEF
4 ADG
5 BDEFH
6 CFI
7 DEGH
8 GHI
9 EFHI
输入9个整数,表示各时钟指针的起始位置,相邻两个整数之间用单个空格隔开。其中,0=12点、1=3点、2=6点、3=9点。输出输出一个最短的移动序列,使得9个时钟的指针都指向12点。按照移动的序号从小到大输出结果。相邻两个整数之间用单个空格隔开。样例输入
3 3 0
2 2 2
2 1 2
样例输出
4 5 8 9 每个钟表有4种拨法,且与顺序无关,枚举即可 4^9种可能
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
#define INF 0x3f3f3f3f;
int ori[][], s[][];
int t[]; bool ok()
{
for (int i = ; i <=; i++) {
for (int j = ; j <=; j++) {
if (s[i][j])
return ;
}
}
return ;
}
int main()
{
//freopen("1.txt", "r", stdin);
for (int i = ; i <= ; i++)
for (int j = ; j <= ; j++)
cin >> ori[i][j]; int Min = INF;
for (int i1 = ; i1 < ; i1++)
for (int i2 = ; i2 < ; i2++)
for (int i3 = ; i3 < ; i3++)
for (int i4 = ; i4 < ; i4++)
for (int i5 = ; i5 < ; i5++)
for (int i6 = ; i6 < ; i6++)
for (int i7 = ; i7 < ; i7++)
for (int i8 = ; i8 < ; i8++)
for (int i9 = ; i9 < ; i9++) {
memcpy(s, ori, sizeof(ori)); //每种枚举情况都是独立的
s[][] = (s[][]+i1+i2+i4)%; //A
s[][] = (s[][]+i1+i2+i3+i5)%;//B
s[][] = (s[][]+i2+i3+i6)%;//C
s[][] = (s[][]+i1+i4+i5+i7)%;//D
s[][] = (s[][]+i1+i3+i5+i7+i9)%;//E
s[][] = (s[][]+i3+i5+i6+i9)%;//F
s[][] = (s[][]+i4+i7+i8)%;//G
s[][] = (s[][]+i5+i7+i8+i9)%;//H
s[][] = (s[][]+i6+i8+i9)%;//I
if (ok()) {
int tot = i1+i2+i3+i4+i5+i6+i7+i8+i9;
// cout << tot << endl;
if (tot < Min) {
Min = tot;
t[] = i1; t[] = i2; t[] = i3;
t[] = i4; t[] = i5; t[] = i6;
t[] = i7; t[] = i8; t[] = i9;
}
} }
for (int i = ; i <= ; i++) {
if (t[i] && i!=) {
for (int j = ; j < t[i]; j++)
cout << i << " ";
}
else if (t[i] && i == ) {
for (int j = ; j < t[i]-; j++)
cout << i << " ";
cout << i;
}
} return ;
}
[poj]开关类问题 枚举 位运算的更多相关文章
- POJ 2436 二进制枚举+位运算
题意:给出n头牛的得病的种类情况,一共有m种病,要求找出最多有K种病的牛的数目: 思路:二进制枚举(得病处为1,否则为0,比如得了2 1两种病,代号就是011(十进制就是3)),首先枚举出1的个数等于 ...
- 深入V8引擎-枚举+位运算实现参数配置
不知不觉都快月底了,看了看上一篇还是6号写的,惭愧惭愧,说好的坚持.为了证明没有偷懒(其实还是沉迷了一会dota2),先上一个图自证清白. 基本上从初始化引擎,到Isolate.handleScope ...
- c#枚举位运算操作
抛出预设问题 需要有一个npc需要在一周中的,周一,周二,周三会出现,其他时间不可见 解决问题 因为一周时间是固定的,所以创建枚举类型比较合适,如下 enum Days { None, Sunday, ...
- POJ 1166 The Clocks [BFS] [位运算]
1.题意:有一组3*3的只有时针的挂钟阵列,每个时钟只有0,3,6,9三种状态:对时针阵列有9种操作,每种操作只对特点的几个时钟拨一次针,即将时针顺时针波动90度,现在试求从初试状态到阵列全部指向0的 ...
- poj 1222 EXTENDED LIGHTS OUT(位运算+枚举)
http://poj.org/problem?id=1222 题意:给一个确定的5*6放入矩阵.每一个格子都有一个开关和一盏灯,0表示灯没亮,1表示灯亮着.让你输出一个5*6的矩阵ans[i][j], ...
- AcWing95. 费解的开关 枚举+位运算
这道题的确比较难想,首先我们知道图比较小,有可能是枚举,那么该如何枚举呢??? 你可以发现,我们只要把第一排定了,并且保证第一排不准动,那么答案就定了 也就是说,我们首先用二进制枚举,枚举第一行需要翻 ...
- [POJ] 2453 An Easy Problem [位运算]
An Easy Problem Description As we known, data stored in the computers is in binary form. The probl ...
- BZOJ 1647 [Usaco2007 Open]Fliptile 翻格子游戏:部分枚举 位运算
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1647 题意: 在一个n*m(1 <= n,m <= 15)的棋盘上,每一个格子 ...
- POJ 1753 bfs+位运算
T_T ++运算符和+1不一样.(i+1)%4 忘带小括号了.bfs函数是bool 型,忘记返回false时的情况了.噢....debug快哭了...... DESCRIPTION:求最少的步骤.使得 ...
随机推荐
- python mmap使用记录
1.写文件 with open('??', 'r+b') as f: with contextlib.closing(mmap.mmap(f.fileno(), size, flags=mmap.MA ...
- 线程池ThreadPoolExcecutor介绍
线程池ThreadPoolExecutor 使用Executors和ThreadPoolExecutor 并发新特性—Executor 框架与线程池
- 前端基础之---css
css 介绍 css 规则有两个主要的部分构成 : 选择器 , 以及一条或多条声明. 现在的互联网前端分为三层 : ● HTML :超文本标签机语言,从语义的角度描述页面结构. ● CSS : 层 ...
- -es6的部分语法
es6的语法 一 . let 和 var 的区别 : 1 . let 和 val 的区别 : ES6新增了let命令 , 用来声明变量,它的用法类似于 var (ES5), 但是所声明的变量,只在l ...
- cinder挂载卷的过程原理
LVM名称介绍 PV:物理磁盘 VG:卷组,多个PV可以组成一个VG,一个VG可以划分成多个LV(逻辑卷). PP:物理区块,将一个VG逻辑的划分成连续的小块. LP:逻辑区块,若干个PP组成一个LP ...
- gcc error - "iostream: No such file or directory"
#include <iostream> using namespace std; int main(void) { cout<<"Hello World!\n&quo ...
- Module.exports和exports的区别
原文链接: https://www.ycjcl.cc/2017/02/10/module-exportshe-exportsde-qu-bie/ 学习Seajs时,看到了exports.doSomet ...
- access 驱动在win64位出现问题
如果是调试的话,将应用程序池的 启动win32应用程序池 为 true
- listen 54
Our library is also open for the local residents. People are doing their Christmas shopping. Later t ...
- listen 56
Kettles Stop Whistling in the Dark British physicist Lord Rayleigh is best known for his discovery o ...