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 ...
随机推荐
- 洛谷P3116 [USACO15JAN]约会时间Meeting Time
P3116 [USACO15JAN]约会时间Meeting Time 题目描述 Bessie and her sister Elsie want to travel from the barn to ...
- 洛谷P2474 [SCOI2008]天平
P2474 [SCOI2008]天平 题目背景 2008四川NOI省选 题目描述 你有n个砝码,均为1克,2克或者3克.你并不清楚每个砝码的重量,但你知道其中一些砝码重量的大小关系.你把其中两个砝码A ...
- 洛谷P4287 [SHOI2011]双倍回文(回文自动机)
传送门 听说有大佬用manacher$O(n)$过此题……太强啦…… 说一下PAM的做法吧.(看了题解之后发现)蛮简单的 我们肯定要先建出回文自动机的 然后如果是枚举每一个节点暴跳fail指针肯定得T ...
- 10分钟了解什么是BFC
BFC对于已经是一个耳熟能详的词汇了,而且在前端面试中,这题也是一个高频题.虽然我们平时在开发的时候知道如何利用BFC来解决问题,但是我们要具体说出BFC的概念和怎么触发BFC,我相信很多小伙伴也是和 ...
- java中的String,StringBuffrer,Stringbuilder的区别
简单描述下 效率:StringBuilder>StringBuffer>String 使用场景: 如果要操作少量的数据用 = String 单线程操作字符串缓冲区 下操作大量数据 = St ...
- 20165224 陆艺杰 Exp 8 Web基础
.基础问题回答 (1)什么是表单 html的一个控件 表单在网页中主要负责数据采集功能 (2)浏览器可以解析运行什么语言 html xml jsp php python 等 (3)WebServer支 ...
- ios 容错处理AvoidCrash
程序因为很多原因容易出现崩溃问题,比如数组越界.空字符串等造成的崩溃 // 在AppDelegate 写如下代码 初始化防止程序因数组和字符串等崩溃问题 //初始化 AvoidCrash (常用对象防 ...
- 项目 08 WebSocket
项目班 08 WebSocket app.py 更新 添加两个路由 handlers = [ ('/', main.IndexHandler), ('/explore', main.ExploreHa ...
- 解决Eclipse导入Gradle项目时在 Building gradle project info 一直卡住
问题描述 在使用 Eclipse 导入 Gradle 项目时一直卡住,不能导入项目 问题解决 解决办法主要有两种:一是直接下载 gradle 离线包,二是修改项目的 ..\gradle\wrapp ...
- about 字节
关于由于赋值导致字节的截断.字节扩展及数据类型的提升: 一.字节截断:int----->char 当一个字节(8位)放不下时,出现截断,直接取(最后一个字节)最后面面8位. 例如:1000000 ...