UVA Live Archive 4490 Help Bubu(状压dp)
难点在于状态设计,从左向右一本书一本书的考虑,每本书的决策有两种拿走或者留下,
对于拿走后的书,之后要放回,但是决策过程中不知道到往哪里放,
虽然前面的书的种类确定,可能是往后面放更优,而后面的书的类型还不确定。对于所有拿出来的书,最后会增加多少段只和书的种类有关。
所以我们用s记录留下书的种类,等到所有书都考虑完了以后一并放回。
对于留下的书,是否成为新的一段和上一次书的高度有关,因此用一个last记录上一次书的种类。(用s来判断一下last不存在的情况)
dp[i = 第i本书][j = 拿了j次][s = 剩下书的种类][last = 上一次书的种类] = 最小混乱度
转移方程见代码
直接for是最好写的
- #include<bits/stdc++.h>
- using namespace std;
- const int maxn = , maxs = <<;
- int dp[][maxn][maxs][];
- int bc[maxs];
- int h[maxn];
- const int INF = 0x3f3f3f3f;
- //#define LOCAL
- int main()
- {
- #ifdef LOCAL
- freopen("in.txt","r",stdin);
- #endif
- for(int i = maxs; i-- ;){
- int x = i;
- while(x){;
- bc[i] += x&;
- x >>= ;
- }
- }
- int ks = , n, k;
- while(scanf("%d%d",&n,&k),n+k){
- int All = ;
- for(int i = ; i < n; i++){
- scanf("%d",h+i);
- h[i] -= ;
- All |= <<h[i];
- }
- memset(dp[],0x3f,sizeof(dp[]));
- dp[][][<<h[]][h[]] = ;
- dp[][][][] = ;
- for(int i = ; i < n; i++){
- int a = i&, b = a^, bs = <<h[i];
- memset(dp[a],0x3f,sizeof(dp[a]));
- for(int j = k; j >= ; j--){
- for(int s = maxs; s--; ){
- for(int ls = ; ls--; ){
- if(dp[b][j][s][ls] < INF){
- dp[a][j][s|bs][h[i]] = min(dp[a][j][s|bs][h[i]], dp[b][j][s][ls] + (s?( h[i] == ls?: ):));
- if(j < k) dp[a][j+][s][ls] = min(dp[a][j+][s][ls], dp[b][j][s][ls]);
- }
- }
- }
- }
- }
- int a = n&^;
- int ans = n+;
- for(int s = maxs; s--;){
- for(int ls = ; ls--; ){
- ans = min(ans, dp[a][k][s][ls] + bc[All^s]);
- }
- }
- printf("Case %d: %d\n\n",++ks,ans);
- }
- return ;
- }
实际上可能有很多状态访问不到的时候,for会枚举到一些无用的状态,这时候可以考虑把有效的状态保存下来,(记忆化搜索也可以避免访问无用状态,但是没办法用滚动数组了)
这样的话不需要对整个dp数组初始化,取代的是需要状态判重。
这样写有种做搜索题的感觉。
- #include<bits/stdc++.h>
- using namespace std;
- const int maxn = , maxs = <<;
- int dp[][maxn][][maxs];
- int vis[maxn][][maxs],clk;
- int h[maxn];
- const int nil = ;
- struct state
- {
- int ct,ls,s;
- }vc[][maxn**maxs];
- int sz[];
- #define dim(x) [x.ct][x.ls][x.s]
- #define add(id,ct,ls,s) vc[id][sz[id]++] = state{ct,ls,s};
- #define psb(id) vc[id][sz[id]++] = y;
- #define clr(id) sz[id] = 0;
- #define edof(id) vc[id][sz[id]]
- #define updata(v)\
- if(vis Td != clk){\
- vis Td = clk;\
- dp[a] Td = v;\
- psb(a);\
- }else {\
- dp[a] Td = min(dp[a] Td, v);\
- }
- inline int bc(int x)
- {
- int re = ;
- while(x){
- re += x&;
- x >>= ;
- }
- return re;
- }
- //#define LOCAL
- int main()
- {
- #ifdef LOCAL
- freopen("in.txt","r",stdin);
- #endif
- int ks = , n, k;
- while(scanf("%d%d",&n,&k),n+k){
- int All = ;
- for(int i = ; i < n; i++){
- scanf("%d",h+i);
- h[i] -= ;
- All |= <<h[i];
- }
- clr();
- state y = {,h[],<<h[]};
- dp[] dim(y) = ;
- psb()
- y = {,nil,};
- dp[] dim(y) = ;
- psb()
- for(int i = ; i < n; i++){
- int a = i&, b = a^, bs = <<h[i];
- clr(a)
- clk++;
- for(int j = ; j < sz[b]; j++){
- auto &x = vc[b][j];
- int val = dp[b] dim(x);
- int tmp = val + ( x.s? ( (x.ls == h[i])?: ) : );
- y = {x.ct,h[i],x.s|bs};
- #define Td [y.ct][y.ls][y.s]
- updata(tmp)
- if(x.ct < k){
- y = {x.ct+, x.ls, x.s};
- updata(val)
- }
- }
- }
- int a = n&^;
- int ans = n+;
- for(int j = ; j < sz[a]; j++){
- auto &x = vc[a][j];
- ans = min(ans, dp[a] dim(x) + bc(All^x.s));
- }
- printf("Case %d: %d\n\n",++ks,ans);
- }
- return ;
- }
UVA Live Archive 4490 Help Bubu(状压dp)的更多相关文章
- UVA 1412 Fund Management (预处理+状压dp)
状压dp,每个状态可以表示为一个n元组,且上限为8,可以用一个九进制来表示状态.但是这样做用数组开不下,用map离散会T. 而实际上很多九进制数很多都是用不上的.因此类似uva 1601 Mornin ...
- 【UVa】Headmaster's Headache(状压dp)
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...
- 【UVA】11825 Hackers' Crackdown(状压dp)
题目 传送门:QWQ 分析 $ n<= 16 $ 显然是状压 然后搞一搞(靠着蓝书yy一下) 代码 #include <bits/stdc++.h> using namespace ...
- uva 11825 Hackers' Crackdown (状压dp,子集枚举)
题目链接:uva 11825 题意: 你是一个黑客,侵入了n台计算机(每台计算机有同样的n种服务),对每台计算机,你能够选择终止一项服务,则他与其相邻的这项服务都终止.你的目标是让很多其它的服务瘫痪( ...
- UVa 10817 - Headmaster's Headache(状压DP)
链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...
- UVA Mega Man's Mission(状压dp)
把消灭了那些机器人作为状态S,预处理出状态S下可以消灭的机器人,转移统计方案.方案数最多16!,要用64bit保存方案. #include<bits/stdc++.h> using nam ...
- UVa 11795 Mega Man's Mission (状压DP)
题意:你最初只有一个武器,你需要按照一定的顺序消灭n个机器人(n<=16).每消灭一个机器人将会得到他的武器. 每个武器只能杀死特定的机器人.问可以消灭所有机器人的顺序方案总数. 析:dp[s] ...
- UVA - 10817 Headmaster's Headache (状压dp+记忆化搜索)
题意:有M个已聘教师,N个候选老师,S个科目,已知每个老师的雇佣费和可教科目,已聘老师必须雇佣,要求每个科目至少两个老师教的情况下,最少的雇佣费用. 分析: 1.为让雇佣费尽可能少,雇佣的老师应教他所 ...
- 状压DP UVA 10817 Headmaster's Headache
题目传送门 /* 题意:学校有在任的老师和应聘的老师,选择一些应聘老师,使得每门科目至少两个老师教,问最少花费多少 状压DP:一看到数据那么小,肯定是状压了.这个状态不好想,dp[s1][s2]表示s ...
随机推荐
- 从零开始安装 Ambari (2) -- 准备本地 repository
安装 Ambari,最后是为了用它部署 hadoop 集群.安装时默认使用的是 hortonworks 远程的资源,用它部署集群时,需要下载 Hadoop.Hive.HBase 的安装包,速度很慢.我 ...
- dbms_xplan的display_cursor查看执行计划
准备工作: SQL> conn sys/root as sysdba Connected. SQL> grant select on v_$sql_plan to scott; Grant ...
- 《算法竞赛进阶指南》1.4Hash
137. 雪花雪花雪花 有N片雪花,每片雪花由六个角组成,每个角都有长度. 第i片雪花六个角的长度从某个角开始顺时针依次记为ai,1,ai,2,-,ai,6. 因为雪花的形状是封闭的环形,所以从任何一 ...
- centos7 yum快速安装php7.1
1. 安装nginx yum install nginx ##开启nginx service nginx start 2.安装MYSQLyum localinstall http://dev.mysq ...
- NppFTP小插件的使用
大家在Linux系统中配置运行环境时,一定会遇到相关配置文件的修改,虽说在Linux系统中可以使用vi,vim的命令进行文本编辑,但是操作起来还是没有在Windows系统中用的爽,特别是操作大文本量的 ...
- Spring 学习(三)AOP
(1)AOP概述 - AOP:面向切面编程,扩展功能不修改源代码实现 - AOP采取横向抽取机制,取代了传统的纵向继承体系重复性代码 (2)AOP底层原理 原始方法------->纵向继承体系 ...
- Storm概念学习系列之storm的特性
不多说,直接上干货! storm的特性 Storm 是一个开源的分布式实时计算系统,可以简单.可靠地处理大量的数据流. Storm支持水平扩展,具有高容错性,保证每个消息都会得到处理,而且处理速度很快 ...
- ZK请求处理
1. 事务请求转发-事务必须由Leader处理 所有非Leader的服务器收到来自客户端的事务请求,都会将客户端请求已REQUEST形式转发给Leader服务器进行处理 2. 事务处理 Proposa ...
- Arduino连接pH计
关于arduino连接ph,核心的东西就是对ph传感器返回的信号值进行一系列的操作,注意因为返回的信号很弱,而且外部环境对其影响也很大,所以需要在电路设计上加入一些功能,比如信号放大.滤波等,电路设计 ...
- vue实现选中列表功能
<template> <div> <ul v-for="prop in items"> <dt>{{prop.name}}</ ...