[UVA12235] Help Bubu 思维题+状态定义+Dp
Online Judge:UVA12235
Label:思维题,状态定义,状压Dp
题面:
题目描述
有一个书架,上面放了n本书,从左往右的第i本书的高度为h[i]。定义书架的混乱度为连续等高段的个数。
例如:{30,30,31,31,32}的混乱度为3;{30,32,32,31}的混乱度为3;{31,32,31,32,31}的混乱度为5。
现在你可以从中抽出至多k本书,然后将他们随意放回书架任意位置,求最终最小的混乱度。
对于100%的数据,N的范围[1,500],K的范围[1,100],书的高度范围[25,32];
输入
第一行两个整数N,K;
第二行,N个元素,表示从左往右每本书的高度。
输出
输出重新摆放K本书的最小混乱度。
"Print a blank line after the output of each case."注意每组数据输出要两个换行!!
样例
Input
5 2
25 25 32 32 25
5 1
25 26 25 26 25
0 0
Output
Case 1: 2
Case 2: 3
题解
发现书的高度只有\([25,32]\)这8种,似乎可以状压的样子。对高度重新编号\(0\)~\(7\)方便后面表示,并且称为\(8\)种不同的颜色。
定义状态\(dp[i][j][sta][co]\),只考虑前\(i\)本书,已经将其中\(j\)本书拿起来了(注意这里是拿起来,其实是采用一种上帝视角,先全部拿出来然后到时候一个一个再放回去),\(sta\)表示哪些颜色的书还没拿起来过(用二进制表示状态),\(co\)表示最近一次没拿起来的书的颜色,Dp值表示此时(i及其之前)剩下来没有移动的那些书的混乱度。
然而你会发现直接这样定数组会MLE,如何优化呢,只要你把题解拉下来一点直接看转移过程,就会发现,对于第一维来说每次只用上一层状态,所以可以滚动一下第一维。这样空间就没问题勒。
先来讲讲接下来具体如何实现:
初态:对于任意\(h∈[h[1],h[n]]\) 有 \(dp[i][i-1][1<<h][h]\)表示,除了当前这本书,前面的\(i-1\)本书都拿起来时的状态;
终态:统计\(dp[n][j][sta][co]+val\)的最小值,其中\(val\)=\(all\) \(Xor\) \(sta\)中1的个数,其实就是那些拿起来的书的颜色种类总数。
而转移呢可以一边读入一边进行。对于当前的高度\(h\)(先-24转化成0~7中的数字),我们枚举\(i,sta,co\),详见下面注释:
inline void Do(int &x,int y){if(x==-1||x>y)x=y;}
//枚举第o本书
int g=0,all=0;
Rep(o,1,n){
//读入高度,预处理下
int h;scanf("%d",&h);h-=25;
//滚动~
g^=1;memset(dp[g],-1,sizeof(dp[g]));
//上面所说的初态初始化。注意要判:o-1<=m,因为第二维我们只开到m的上限100,不特判可能会数组越界
if(o-1<=m)dp[g][o-1][1<<h][h]=1;
//i:已拿个数 s:未选颜色状态 c:最近一次没动的书的颜色
Rep(i,0,min(o,m))Rep(s,1,all)Rep(c,0,7){//枚举上一层状态
if(dp[g^1][i][s][c]==-1)continue;
//最近的位置上有一个跟h颜色相同的书没拿走,很明显把当前这个留下来较优
if(h==c)Do(dp[g][i][s][c],dp[g^1][i][s][c]);
else{
//把当前这个留在原位,由于前面一个跟自己颜色不同,所以混乱值+1
Do(dp[g][i][s|(1<<h)][h],dp[g^1][i][s][c]+1);
//把当前这个拿起来
Do(dp[g][i+1][s][c],dp[g^1][i][s][c]);
}
}
all|=1<<h;//all表示当前已经含有的颜色
}
最后的统计根据上面的终态来就好了。
上完整代码:
#include<bits/stdc++.h>
#define Rep(a,b,c) for(int a=b;a<=c;++a)
using namespace std;
int n,m,dp[2][115][260][10];
inline void Do(int &x,int y){
if(x==-1||x>y)x=y;
}
int main(){
int cas=0;
while(~scanf("%d%d",&n,&m)){
if(n==0||m==0)return 0;memset(dp,-1,sizeof(dp));
int g=0,all=0;
Rep(o,1,n){
int h;scanf("%d",&h);h-=25;
g^=1;memset(dp[g],-1,sizeof(dp[g]));
if(o-1<=m)dp[g][o-1][1<<h][h]=1;
Rep(i,0,min(o,m))Rep(s,1,all)Rep(c,0,7){
if(dp[g^1][i][s][c]==-1)continue;
if(h==c)Do(dp[g][i][s][c],dp[g^1][i][s][c]);
else{
Do(dp[g][i][s|(1<<h)][h],dp[g^1][i][s][c]+1);
Do(dp[g][i+1][s][c],dp[g^1][i][s][c]);
}
}
all|=1<<h;
}
int ans=n;
Rep(i,0,m)Rep(s,1,all)Rep(c,0,7)if(~dp[g][i][s][c]){
int cnt=0,choose=all^s;
Rep(o,0,7)if((1<<o)&choose)cnt++;
ans=min(ans,dp[g][i][s][c]+cnt);
}
printf("Case %d: %d\n\n",++cas,ans);
}
}
End
重新看一遍这道题,难点主要在于正确定义状态。状压、滚动这两个优化根据数据范围和转移过程并不难想。为什么可以以这样的顺序从前到后遍历转移呢,考试的时候也有思考过这样的顺序,但是马上能找到反例——可能前面的书也可以放在他之后的块里。实际上还是没有想通那个上帝视角,即将这些拿出来的书先囤着,到时候一个一个贪心的插♂回去,不急着确定出到底要放在哪个块里。
[UVA12235] Help Bubu 思维题+状态定义+Dp的更多相关文章
- 思维题练习专场-DP篇(附题表)
转载请注明原文地址http://www.cnblogs.com/LadyLex/p/8536399.html 听说今年省选很可怕?刷题刷题刷题 省选已经结束了但是我们要继续刷题刷题刷题 目标是“有思维 ...
- Educational Codeforces Round 59 (Rated for Div. 2) E 区间dp + 状态定义 + dp预处理(分步dp)
https://codeforces.com/contest/1107/problem/E 题意 给出01字符串s(n<=100),相邻且相同的字符可以同时消去,一次性消去i个字符的分数是\(a ...
- 【思维题 状压dp】APC001F - XOR Tree
可能算是道中规中矩的套路题吧…… Time limit : 2sec / Memory limit : 256MB Problem Statement You are given a tree wit ...
- hdu 5119 (类似于划分数的状态定义) (DP中的计数问题)
题目描述:求n个数中异或值大于m的方案数有多少个? 设状态f[i][j]代表前i个数异或值为j的方案数有f[i][j]种,那么对于j来说要么选第i个数与前面的i-1个数中的某些数构成j,f[i-1][ ...
- [Hdu-5155] Harry And Magic Box[思维题+容斥,计数Dp]
Online Judge:Hdu5155 Label:思维题+容斥,计数Dp 题面: 题目描述 给定一个大小为\(N*M\)的神奇盒子,里面每行每列都至少有一个钻石,问可行的排列方案数.由于答案较大, ...
- [SHOI2007] 书柜的尺寸 思维题+Dp+空间优化
Online Judge:Luogu-P2160 Label:思维题,Dp,空间优化 题面: 题目描述 给\(N\)本书,每本书有高度\(Hi\),厚度\(Ti\).要摆在一个三层的书架上. 书架的宽 ...
- BZOJ 2734 洛谷 3226 [HNOI2012]集合选数【状压DP】【思维题】
[题解] 思维题,看了别人的博客才会写. 写出这样的矩阵: 1,3,9,... 2,6,18,... 4,12.36,... 8,24,72,... 我们要做的就是从矩阵中选出一些数字,但是不能选相邻 ...
- hdu6006 Engineer Assignment 状态dp 定义dp[i][s]表示前i个工程状态为s可以执行的最大工程数。s表示前i个工人选走了s状态的工程师。
/** 题目:hdu6006 Engineer Assignment 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6006 题意:已知n个工程,每个需要某 ...
- 状态压缩dp增量统计贡献——cf1238E(好题)
这题的状态设计非常巧妙,因为dp[S]表示的并非当前正确的值,而是维护一个中间量,这个中间量在到达末状态时才正确 当然官方的题解其实更加直观,只不过理解起来其实有点困难 /* 给定一个串s,字符集为2 ...
随机推荐
- js 高级 原型与原型链
* 所有函数都有一个特别的属性: * `prototype` : 显式原型属性* 所有实例对象都有一个特别的属性: * `__proto__` : 隐式原型属性 1. 每个函数都有一个prototy ...
- js实现F5键刷新后菜单保持之前状态以及监听F5页面刷新子iframe 而父页面不刷新
利用layui实现菜单效果时,刷新页面仍回到首页状态,需要 实现iframe子页面刷新父元素不刷新,下面是代码 //刷新时禁用F5的默认事件 $(document).keydown(function ...
- IDEA快捷键(收集自网络后整理)
快捷键 说明 CTRL+B 快速打开光标处的类或方法 CTRL+C 拷贝 CTRL+D 复制当前行到下一行 CTRL+E 最近打开的文件 CTRL+F 当前文件查找特定内容 CTRL+G 定位行 CT ...
- Java 基础 - 如何重写equals()
ref:https://www.cnblogs.com/TinyWalker/p/4834685.html -------------------- 编写equals方法的建议: 显示参数命名为oth ...
- Python: 生成器与迭代 generators and iteration
https://eastlakeside.gitbooks.io/interpy-zh/content/Generators/ 文章不是非常好 1,三个概念 可迭代对象 iterable, 迭代器 i ...
- LOIC Download
{ //https://github.com/NewEraCracker/LOIC }
- Windows shutdown
用法: shutdown [/i | /l | /s | /sg | /r | /g | /a | /p | /h | /e | /o] [/hybrid] [/soft] [/fw] [/f] ...
- 阿里云在云栖大会发布RPA最新3.4版本,将与达摩院联合探索人工智能领域
9月26日,在2019年杭州云栖大会上,阿里云发布了RPA最新V3.4版本,全新升级了增加诸如录屏审计.JAVA应用录制能力.达摩院OCR内置组件.语法检查与智能提示能力增强等功能. RPA全名称Ro ...
- 字符串——cf1109B
/* 先判不可行的情况:n/2的是单一字符 判只切割一次能不能组成回文 枚举每个切割点,交换两个串的位置 剩下就是割两次 */ #include<bits/stdc++.h> #inclu ...
- angular2 组件内容嵌入(ng-content)
一.简介 内容嵌入是组件的一个高级功能特性,使用组件的内容嵌入特性能很好地扩充组件的功能,方便代码的复用. 二.用法 如上,在模版中使用了<ng-content>标签,这个标签就是用来渲染 ...