UVALive 4490 Help Bubu
题目大意:有n本书,高度值域为8,现可以把k本书拿出来再放进去,相邻的、高度相同的书算作一块,最小化块的个数。n=100。
强烈建议大家不要在做完区间DP后做别的DP题:区间DP是整体考虑,而一般DP是考虑以i为末尾,思路完全不同。
难点好像就在于设状态,状态设出来就可以大力转移了。
首先f[i][j],表示到第几本书、用了几次是肯定要设的,但是这样做会缺少很多信息。在转移的时候,我们需要知道最后一位是什么?所以开到f[i][j][k]。
这个就可以DP了。但是答案怎么统计呢?如果最终答案是把几种高度全部扣出来,答案就要比DP值大,但这是我们状态中不能体现的。
看到值域这么小,直接设f[i][j][k][l],表示到第i本书、用了j次取书机会、在书架上的书的集合是k,最后一本书是l的最小块数。
初始化:
- f[i+][i][bin[h[i+]]][h[i+]]=;
初始化
转移方程就是讨论一下就可以出来的东西了。
1.当前书取出来:
- f[i+][j+][k][l]=min(f[i+][j+][k][l],f[i][j][k][l]);
转移1
2.当前书不取,这时要与最后一位做比较:
- f[i+][j][k|bin[h[i+]]][h[i+]]=min(f[i+][j][k|bin[h[i+]]][h[i+]],f[i][j][k][l]+(h[i+]!=l));
转移2
其中bin表示2的多少次方。
在统计答案的时候,要这么统计:
- for(int i=;i<=k;++i)
- for(int j=;j<bin[];++j)
- for(int k=;k<;++k)
- if(f[n][i][j][k]!=f[][][][])
- Ans=min(Ans,f[n][i][j][k]+num[U^j]);
统计答案
其中num表示二进制下有多少个1。
完整代码:
- #include <iostream>
- #include <cstdio>
- #include <cstdlib>
- #include <algorithm>
- #include <vector>
- #include <cstring>
- #include <queue>
- #include <complex>
- #include <stack>
- #define LL long long int
- #define dob double
- #define FILE "4490"
- using namespace std;
- const int N = ;
- int n,k,bin[],h[N],f[N][N][<<][],t,Ans,num[<<];
- inline int gi(){
- int x=,res=;char ch=getchar();
- while(ch>''||ch<''){if(ch=='-')res*=-;ch=getchar();}
- while(ch<=''&&ch>='')x=x*+ch-,ch=getchar();
- return x*res;
- }
- inline void Min(int &x,int y){
- if(x>y)x=y;
- }
- inline void solve(int U=){
- for(int i=;i<=n;++i)U|=bin[h[i]=gi()-];
- memset(f,/,sizeof(f));Ans=f[][][][];
- f[][][bin[h[]]][h[]]=;
- for(int i=;i<n;++i){
- f[i+][i][bin[h[i+]]][h[i+]]=;
- for(int j=;j<=i && j<=k;++j)
- for(int k=;k<bin[];++k)
- for(int l=;l<;++l)
- if(f[i][j][k][l]!=Ans){
- Min(f[i+][j+][k][l],f[i][j][k][l]);
- Min(f[i+][j][k|bin[h[i+]]][h[i+]],f[i][j][k][l]+(h[i+]!=l));
- }
- }
- for(int i=;i<=k;++i)
- for(int j=;j<bin[];++j)
- for(int k=;k<;++k)
- if(f[n][i][j][k]!=f[][][][])
- Min(Ans,f[n][i][j][k]+num[U^j]);
- printf("Case %d: %d\n\n",++t,Ans);
- }
- int main()
- {
- freopen(FILE".in","r",stdin);
- freopen(FILE".out","w",stdout);
- bin[]=;for(int i=;i<;++i)bin[i]=bin[i-]*;
- for(int i=;i<bin[];++i)num[i]=num[i/]+(i&);
- while((n=gi()) && (k=gi()))solve();
- fclose(stdin);fclose(stdout);
- return ;
- }
Help Bubu
UVALive 4490 Help Bubu的更多相关文章
- Help Bubu UVALive - 4490
传送门 题目大意 有n本书,最多k次操作,每次操作可以把一本书拿出来,放到一个位置去,有一个指标较mess度,他是书的高度的段数,连续的书高度一样算一段,现在给你最先开始各个位置上的书的高度,求操作后 ...
- UVALive 4490 压缩DP
转载自http://blog.csdn.net/zstu_zlj/article/details/9903589 没有接触过压缩DP.位运算也不太熟.所以理解了思路还是不懂代码.
- UVA Live Archive 4490 Help Bubu(状压dp)
难点在于状态设计,从左向右一本书一本书的考虑,每本书的决策有两种拿走或者留下, 对于拿走后的书,之后要放回,但是决策过程中不知道到往哪里放, 虽然前面的书的种类确定,可能是往后面放更优,而后面的书的类 ...
- UVALive - 4108 SKYLINE[线段树]
UVALive - 4108 SKYLINE Time Limit: 3000MS 64bit IO Format: %lld & %llu Submit Status uDebug ...
- UVALive - 3942 Remember the Word[树状数组]
UVALive - 3942 Remember the Word A potentiometer, or potmeter for short, is an electronic device wit ...
- UVALive - 3942 Remember the Word[Trie DP]
UVALive - 3942 Remember the Word Neal is very curious about combinatorial problems, and now here com ...
- 思维 UVALive 3708 Graveyard
题目传送门 /* 题意:本来有n个雕塑,等间距的分布在圆周上,现在多了m个雕塑,问一共要移动多少距离: 思维题:认为一个雕塑不动,视为坐标0,其他点向最近的点移动,四舍五入判断,比例最后乘会10000 ...
- UVALive 6145 Version Controlled IDE(可持久化treap、rope)
题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...
- UVALive 6508 Permutation Graphs
Permutation Graphs Time Limit:3000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Submit ...
随机推荐
- JavaScript(五):函数(闭包,eval)
1.函数的申明:三种方法: function命令 函数表达式:变量赋值 Function构造函数 //method 1: function命令 function test(){ console.log ...
- TestLink使用
- C#开发Windows窗体应用程序的步骤
使用C#开发应用程序时,一般包括创建项目.界面设计.设置属性.编写程序代码.保存项目.程序运行等6个步骤. 1.创建项目 在Visual Studio2017开发环境中选择“文件”→“新建”→“项目” ...
- 计算出前N项的数据
#include<iostream> #include<algorithm> #include<numeric> using namespace std; ; in ...
- JavaScript OOP(二):this关键字以及call、apply、bind
JavaScript的this关键字非常灵活! this 返回的总是对象:即返回属性或方法"当前"所在的对象 var o1={ name:'apple', age:100, msg ...
- mysql索引优化面试题
曾经偷偷的面试了两个单位,都提到了Mysql的优化问题,所以以后要多多学习数据库的优化知识了.建设数据库的优化大概主要就是索引的优化了吧,因为我们不可能修改数据结构的情况下,提高数据库的查询效率似乎也 ...
- Pythonh中的zip()与*zip()函数详解
前言 实验环境: Python 3.6: 示例代码地址:下载示例: 本文中元素是指列表.元组.字典等集合类数据类型中的下一级项目(可能是单个元素或嵌套列表). zip(*iterables)函数详解 ...
- linux服务器解压缩文件的命令
尝试去好好用linux.新手起步. 这边只会提到我用过的.其他相关的以后我用到了我会补充的.如果有错欢迎指正 注:1.c-创建-create 2.v-复杂输出 3.f-文件-file ...
- java 类加载机制总结
Java程序的运行,离不开class的加载,所谓类加载就是将编译好的class文件加载的jvm并形成class对象,只有class正确加载才能被实例化和调用. public class test { ...
- Memory Monitor
Heap Viewer,Memory Monitor和Allocation Tracker是用来可视化你的app使用内存的补充工具. 使用Memory Monitor Tool来发现是否有不好的内存回 ...