洛谷 P2622 关灯问题II(状压DP入门题)
https://www.cnblogs.com/violet-acmer/p/9852294.html
题解:
相关变量解释:
int n,m;
int a[maxn][];//a[i][j] : 第i个开关对第j个灯的效果。
bool vis[R()];//vis[i] : 判断状态i是否被访问过
struct Node
{
int status;//状态
int minTimes;//来到当前状态按下开关的最小次数
Node(int a=,int b=):status(a),minTimes(b){}
};
queue<Node >myqueue;//用队列中的状态去解锁其他为解锁(访问)过的状态,并能保证被解锁的状态的minTimes最小
步骤:
(1):将Node( (1<<n)+1,0 ) 加入队列,因为初始等全是亮的,对应到二进制就是n个1,并且需要 0 次按下开关。
(2):从队头依次弹出元素,并用当前状态去解锁其他状态,并能保证被其解锁的状态的minTimes是最小的。
(3):重复(2)过程,直到找到 0 状态或队列为空
AC代码:
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define R(x) (1<<x)
const int maxn=+; int n,m;
int a[maxn][];//a[i][j] : 第i个开关对第j个灯的效果。
bool vis[R()];//vis[i] : 判断状态i是否被访问过
struct Node
{
int status;//状态
int minTimes;//来到当前状态按下开关的最小次数
Node(int a=,int b=):status(a),minTimes(b){}
};
queue<Node >myqueue;//用队列中的状态去解锁其他为解锁(访问)过的状态,并能保证被解锁的状态的minTimes最小 int nextStatus(int nowStatus,int i)
{
int x=nowStatus;
for(int j=;j <= n;++j)//从右往左一一对应
{
if(a[i][j] == && (x>>(j-)&))//一定要注意判断x的第j为是否为1
x ^= (<<(j-));//^ : 相同为0,不同为1
else if(a[i][j] == -)
x |= (<<(j-));
}
return x;
}
int updataQ(Node node)
{
for(int i=;i <= m;++i)
{
int status=nextStatus(node.status,i);//找到当前状态node.status可以解锁的下一状态
if(!vis[status])//如果被访问过,那么其minTimes肯定要小于当前的minTimes+1
myqueue.push(Node(status,node.minTimes+)),vis[status]=true;
if(status == )//判断被解锁的状态是否为0状态
return node.minTimes+;
}
return ;
}
int Solve()
{
mem(vis,false);
while(!myqueue.empty())
myqueue.pop();
myqueue.push(Node(R(n)-,));//步骤(1)
while(!myqueue.empty())//步骤(2)(3)
{
Node node=myqueue.front();
myqueue.pop();
int res=updataQ(node);//更新队列中的状态
if(res != )//判断被解锁的状态是否有0状态,如果有,直接输出,一定是最小的按下次数
return res;
}
return -;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i <= m;++i)
for(int j=n;j >= ;--j)//j : n down 1 用意:与二进制的位数一一对应(从右往左)
scanf("%d",a[i]+j);
printf("%d\n",Solve());
}
洛谷 P2622 关灯问题II(状压DP入门题)的更多相关文章
- 关灯问题II 状压DP
关灯问题II 状压DP \(n\)个灯,\(m\)个按钮,每个按钮都会对每个灯有不同影响,问最少多少次使灯熄完. \(n\le 10,m\le 100\) 状压DP的好题,体现了状压的基本套路与二进制 ...
- 洛谷 P2622 关灯问题II【状压DP;隐式图搜索】
题目描述 现有n盏灯,以及m个按钮.每个按钮可以同时控制这n盏灯--按下了第i个按钮,对于所有的灯都有一个效果.按下i按钮对于第j盏灯,是下面3中效果之一:如果a[i][j]为1,那么当这盏灯开了的时 ...
- 洛谷 P2622 关灯问题II【状压DP】
传送门:https://www.luogu.org/problemnew/show/P2622 题面: 题目描述 现有n盏灯,以及m个按钮.每个按钮可以同时控制这n盏灯--按下了第i个按钮,对于所有的 ...
- 洛谷P2622 关灯问题II
洛谷题目链接 声明: 本篇文章不讲基础,对萌新不太友好,(我就是萌新),要学状压$dp$的请另寻,这篇文章只是便于本人查看.... 首先看到$n<=10$,就可以考虑状压了,要求最小值,所以初始 ...
- 【题解】洛谷P3959 [NOIP2017TG] 宝藏(状压DP+DFS)
洛谷P3959:https://www.luogu.org/problemnew/show/P3959 前言 NOIP2017时还很弱(现在也很弱 看出来是DP 但是并不会状压DP 现在看来思路并不复 ...
- 洛谷 P1278 单词游戏 【状压dp】
题目描述 Io和Ao在玩一个单词游戏. 他们轮流说出一个仅包含元音字母的单词,并且后一个单词的第一个字母必须与前一个单词的最后一个字母一致. 游戏可以从任何一个单词开始. 任何单词禁止说两遍,游戏中只 ...
- 洛谷P2704 [NOI2001]炮兵阵地 [状压DP]
题目传送门 炮兵阵地 题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图 ...
- 洛谷P2761 软件补丁问题(状压DP,SPFA)
题意 描述不清... Sol 网络流24题里面怎么会有状压dp?? 真是狗血,不过还是简单吧. 直接用$f[sta]$表示当前状态为$sta$时的最小花费 转移的时候枚举一下哪一个补丁可以搞这个状态 ...
- 洛谷P2831 愤怒的小鸟——贪心?状压DP
题目:https://www.luogu.org/problemnew/show/P2831 一开始想 n^3 贪心来着: 先按 x 排个序,那么第一个不就一定要打了么? 在枚举后面某一个,和它形成一 ...
随机推荐
- python数据结构与算法第四天【代码执行时间测试模块】
#!/usr/bin/env python # _*_ coding:UTF-8 _*_ from timeit import Timer def foo(): ''' 使用append方式向列表添加 ...
- 实用的几个JS新特性(es 2016)
在Chrome 55下测试,可用. 1.箭头函数(arrow function) 以前写的匿名函数是这样的 function(){}, 现在可以简单写成这样()=>{} 如果直接return,没 ...
- gevent监测单线程下的io进行切换
from gevent import monkey;monkey.patch_all() import gevent import time def eat(name): print('%s eat ...
- 【python练习题】程序10
#10.题目:暂停一秒输出,并格式化当前时间. import time print(time.time())#timestamp print(time.localtime(time.time()))# ...
- Zookeeper注册中心底层实现小记
内容摘自微信公众号,程序员小灰.推荐-ing Zookeeper的数据模型 Zookeeper的数据模型是什么样子呢?它很像数据结构当中的树,也很像文件系统的目录. 树是由节点所组成,Zookeepe ...
- centos安装桌面,下面的几个包缺一不可
yum groupinstall “X window system” yum groupinstall “Desktop” yum groupinstall “Chinese Support” 不然的 ...
- BZOJ4519[Cqoi2016]不同的最小割——最小割树+map
题目描述 学过图论的同学都知道最小割的概念:对于一个图,某个对图中结点的划分将图中所有结点分成 两个部分,如果结点s,t不在同一个部分中,则称这个划分是关于s,t的割.对于带权图来说,将 所有顶点处在 ...
- 洛谷P1216数字三角形题解
题目 这道题是一个典型的DP,可以用倒推,顺推的方法,来解这道题.当然用不同的方法他的循环次序是不一样的,所以我们一定要深刻地理解题目的大意,再采用状态转移方程与边界每次求出最优解,并记录循环一遍后就 ...
- BZOJ 1912 巡逻(算竞进阶习题)
树的直径 这题如果k=1很简单,就是在树的最长链上加个环,这样就最大化的减少重复的路程 但是k=2的时候需要考虑两个环的重叠部分,如果没有重叠部分,则和k=1的情况是一样的,但是假如有重叠部分,我们可 ...
- hdu 2955 Robberies (01背包)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=2955 思路:一开始看急了,以为概率是直接相加的,wa了无数发,这道题目给的是被抓的概率,我们应该先求出总的 ...