题目大意:有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的最小块数。

  初始化:

  1. f[i+][i][bin[h[i+]]][h[i+]]=;

初始化

  转移方程就是讨论一下就可以出来的东西了。

  1.当前书取出来:

  1. f[i+][j+][k][l]=min(f[i+][j+][k][l],f[i][j][k][l]);

转移1

  2.当前书不取,这时要与最后一位做比较:

  1. 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的多少次方。

  在统计答案的时候,要这么统计:

  1. for(int i=;i<=k;++i)
  2. for(int j=;j<bin[];++j)
  3. for(int k=;k<;++k)
  4. if(f[n][i][j][k]!=f[][][][])
  5. Ans=min(Ans,f[n][i][j][k]+num[U^j]);

统计答案

  其中num表示二进制下有多少个1。

  完整代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <algorithm>
  5. #include <vector>
  6. #include <cstring>
  7. #include <queue>
  8. #include <complex>
  9. #include <stack>
  10. #define LL long long int
  11. #define dob double
  12. #define FILE "4490"
  13. using namespace std;
  14.  
  15. const int N = ;
  16. int n,k,bin[],h[N],f[N][N][<<][],t,Ans,num[<<];
  17.  
  18. inline int gi(){
  19. int x=,res=;char ch=getchar();
  20. while(ch>''||ch<''){if(ch=='-')res*=-;ch=getchar();}
  21. while(ch<=''&&ch>='')x=x*+ch-,ch=getchar();
  22. return x*res;
  23. }
  24.  
  25. inline void Min(int &x,int y){
  26. if(x>y)x=y;
  27. }
  28.  
  29. inline void solve(int U=){
  30. for(int i=;i<=n;++i)U|=bin[h[i]=gi()-];
  31. memset(f,/,sizeof(f));Ans=f[][][][];
  32. f[][][bin[h[]]][h[]]=;
  33. for(int i=;i<n;++i){
  34. f[i+][i][bin[h[i+]]][h[i+]]=;
  35. for(int j=;j<=i && j<=k;++j)
  36. for(int k=;k<bin[];++k)
  37. for(int l=;l<;++l)
  38. if(f[i][j][k][l]!=Ans){
  39. Min(f[i+][j+][k][l],f[i][j][k][l]);
  40. Min(f[i+][j][k|bin[h[i+]]][h[i+]],f[i][j][k][l]+(h[i+]!=l));
  41. }
  42. }
  43. for(int i=;i<=k;++i)
  44. for(int j=;j<bin[];++j)
  45. for(int k=;k<;++k)
  46. if(f[n][i][j][k]!=f[][][][])
  47. Min(Ans,f[n][i][j][k]+num[U^j]);
  48. printf("Case %d: %d\n\n",++t,Ans);
  49. }
  50.  
  51. int main()
  52. {
  53. freopen(FILE".in","r",stdin);
  54. freopen(FILE".out","w",stdout);
  55. bin[]=;for(int i=;i<;++i)bin[i]=bin[i-]*;
  56. for(int i=;i<bin[];++i)num[i]=num[i/]+(i&);
  57. while((n=gi()) && (k=gi()))solve();
  58. fclose(stdin);fclose(stdout);
  59. return ;
  60. }

Help Bubu

UVALive 4490 Help Bubu的更多相关文章

  1. Help Bubu UVALive - 4490

    传送门 题目大意 有n本书,最多k次操作,每次操作可以把一本书拿出来,放到一个位置去,有一个指标较mess度,他是书的高度的段数,连续的书高度一样算一段,现在给你最先开始各个位置上的书的高度,求操作后 ...

  2. UVALive 4490 压缩DP

    转载自http://blog.csdn.net/zstu_zlj/article/details/9903589 没有接触过压缩DP.位运算也不太熟.所以理解了思路还是不懂代码.

  3. UVA Live Archive 4490 Help Bubu(状压dp)

    难点在于状态设计,从左向右一本书一本书的考虑,每本书的决策有两种拿走或者留下, 对于拿走后的书,之后要放回,但是决策过程中不知道到往哪里放, 虽然前面的书的种类确定,可能是往后面放更优,而后面的书的类 ...

  4. UVALive - 4108 SKYLINE[线段树]

    UVALive - 4108 SKYLINE Time Limit: 3000MS     64bit IO Format: %lld & %llu Submit Status uDebug ...

  5. UVALive - 3942 Remember the Word[树状数组]

    UVALive - 3942 Remember the Word A potentiometer, or potmeter for short, is an electronic device wit ...

  6. UVALive - 3942 Remember the Word[Trie DP]

    UVALive - 3942 Remember the Word Neal is very curious about combinatorial problems, and now here com ...

  7. 思维 UVALive 3708 Graveyard

    题目传送门 /* 题意:本来有n个雕塑,等间距的分布在圆周上,现在多了m个雕塑,问一共要移动多少距离: 思维题:认为一个雕塑不动,视为坐标0,其他点向最近的点移动,四舍五入判断,比例最后乘会10000 ...

  8. UVALive 6145 Version Controlled IDE(可持久化treap、rope)

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...

  9. UVALive 6508 Permutation Graphs

    Permutation Graphs Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit ...

随机推荐

  1. JavaScript(五):函数(闭包,eval)

    1.函数的申明:三种方法: function命令 函数表达式:变量赋值 Function构造函数 //method 1: function命令 function test(){ console.log ...

  2. TestLink使用

  3. C#开发Windows窗体应用程序的步骤

    使用C#开发应用程序时,一般包括创建项目.界面设计.设置属性.编写程序代码.保存项目.程序运行等6个步骤. 1.创建项目 在Visual Studio2017开发环境中选择“文件”→“新建”→“项目” ...

  4. 计算出前N项的数据

    #include<iostream> #include<algorithm> #include<numeric> using namespace std; ; in ...

  5. JavaScript OOP(二):this关键字以及call、apply、bind

    JavaScript的this关键字非常灵活! this 返回的总是对象:即返回属性或方法"当前"所在的对象 var o1={ name:'apple', age:100, msg ...

  6. mysql索引优化面试题

    曾经偷偷的面试了两个单位,都提到了Mysql的优化问题,所以以后要多多学习数据库的优化知识了.建设数据库的优化大概主要就是索引的优化了吧,因为我们不可能修改数据结构的情况下,提高数据库的查询效率似乎也 ...

  7. Pythonh中的zip()与*zip()函数详解

    前言 实验环境: Python 3.6: 示例代码地址:下载示例: 本文中元素是指列表.元组.字典等集合类数据类型中的下一级项目(可能是单个元素或嵌套列表). zip(*iterables)函数详解 ...

  8. linux服务器解压缩文件的命令

    尝试去好好用linux.新手起步.   这边只会提到我用过的.其他相关的以后我用到了我会补充的.如果有错欢迎指正 注:1.c-创建-create 2.v-复杂输出    3.f-文件-file     ...

  9. java 类加载机制总结

    Java程序的运行,离不开class的加载,所谓类加载就是将编译好的class文件加载的jvm并形成class对象,只有class正确加载才能被实例化和调用. public class test { ...

  10. Memory Monitor

    Heap Viewer,Memory Monitor和Allocation Tracker是用来可视化你的app使用内存的补充工具. 使用Memory Monitor Tool来发现是否有不好的内存回 ...