难点在于状态设计,从左向右一本书一本书的考虑,每本书的决策有两种拿走或者留下,

对于拿走后的书,之后要放回,但是决策过程中不知道到往哪里放,

虽然前面的书的种类确定,可能是往后面放更优,而后面的书的类型还不确定。对于所有拿出来的书,最后会增加多少段只和书的种类有关。

所以我们用s记录留下书的种类,等到所有书都考虑完了以后一并放回。

对于留下的书,是否成为新的一段和上一次书的高度有关,因此用一个last记录上一次书的种类。(用s来判断一下last不存在的情况)

dp[i = 第i本书][j = 拿了j次][s = 剩下书的种类][last = 上一次书的种类] = 最小混乱度

转移方程见代码

直接for是最好写的

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3.  
  4. const int maxn = , maxs = <<;
  5. int dp[][maxn][maxs][];
  6. int bc[maxs];
  7. int h[maxn];
  8. const int INF = 0x3f3f3f3f;
  9.  
  10. //#define LOCAL
  11. int main()
  12. {
  13. #ifdef LOCAL
  14. freopen("in.txt","r",stdin);
  15. #endif
  16. for(int i = maxs; i-- ;){
  17. int x = i;
  18. while(x){;
  19. bc[i] += x&;
  20. x >>= ;
  21. }
  22. }
  23. int ks = , n, k;
  24. while(scanf("%d%d",&n,&k),n+k){
  25. int All = ;
  26. for(int i = ; i < n; i++){
  27. scanf("%d",h+i);
  28. h[i] -= ;
  29. All |= <<h[i];
  30. }
  31. memset(dp[],0x3f,sizeof(dp[]));
  32. dp[][][<<h[]][h[]] = ;
  33. dp[][][][] = ;
  34. for(int i = ; i < n; i++){
  35. int a = i&, b = a^, bs = <<h[i];
  36. memset(dp[a],0x3f,sizeof(dp[a]));
  37. for(int j = k; j >= ; j--){
  38. for(int s = maxs; s--; ){
  39. for(int ls = ; ls--; ){
  40. if(dp[b][j][s][ls] < INF){
  41. dp[a][j][s|bs][h[i]] = min(dp[a][j][s|bs][h[i]], dp[b][j][s][ls] + (s?( h[i] == ls?: ):));
  42. if(j < k) dp[a][j+][s][ls] = min(dp[a][j+][s][ls], dp[b][j][s][ls]);
  43. }
  44. }
  45. }
  46. }
  47. }
  48. int a = n&^;
  49. int ans = n+;
  50. for(int s = maxs; s--;){
  51. for(int ls = ; ls--; ){
  52. ans = min(ans, dp[a][k][s][ls] + bc[All^s]);
  53. }
  54. }
  55. printf("Case %d: %d\n\n",++ks,ans);
  56. }
  57. return ;
  58. }

实际上可能有很多状态访问不到的时候,for会枚举到一些无用的状态,这时候可以考虑把有效的状态保存下来,(记忆化搜索也可以避免访问无用状态,但是没办法用滚动数组了)

这样的话不需要对整个dp数组初始化,取代的是需要状态判重。

这样写有种做搜索题的感觉。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3.  
  4. const int maxn = , maxs = <<;
  5. int dp[][maxn][][maxs];
  6. int vis[maxn][][maxs],clk;
  7.  
  8. int h[maxn];
  9.  
  10. const int nil = ;
  11. struct state
  12. {
  13. int ct,ls,s;
  14. }vc[][maxn**maxs];
  15.  
  16. int sz[];
  17. #define dim(x) [x.ct][x.ls][x.s]
  18. #define add(id,ct,ls,s) vc[id][sz[id]++] = state{ct,ls,s};
  19. #define psb(id) vc[id][sz[id]++] = y;
  20. #define clr(id) sz[id] = 0;
  21. #define edof(id) vc[id][sz[id]]
  22.  
  23. #define updata(v)\
  24. if(vis Td != clk){\
  25. vis Td = clk;\
  26. dp[a] Td = v;\
  27. psb(a);\
  28. }else {\
  29. dp[a] Td = min(dp[a] Td, v);\
  30. }
  31.  
  32. inline int bc(int x)
  33. {
  34. int re = ;
  35. while(x){
  36. re += x&;
  37. x >>= ;
  38. }
  39. return re;
  40. }
  41.  
  42. //#define LOCAL
  43. int main()
  44. {
  45. #ifdef LOCAL
  46. freopen("in.txt","r",stdin);
  47. #endif
  48. int ks = , n, k;
  49. while(scanf("%d%d",&n,&k),n+k){
  50. int All = ;
  51. for(int i = ; i < n; i++){
  52. scanf("%d",h+i);
  53. h[i] -= ;
  54. All |= <<h[i];
  55. }
  56. clr();
  57. state y = {,h[],<<h[]};
  58. dp[] dim(y) = ;
  59. psb()
  60. y = {,nil,};
  61. dp[] dim(y) = ;
  62. psb()
  63. for(int i = ; i < n; i++){
  64. int a = i&, b = a^, bs = <<h[i];
  65. clr(a)
  66. clk++;
  67. for(int j = ; j < sz[b]; j++){
  68. auto &x = vc[b][j];
  69. int val = dp[b] dim(x);
  70. int tmp = val + ( x.s? ( (x.ls == h[i])?: ) : );
  71. y = {x.ct,h[i],x.s|bs};
  72. #define Td [y.ct][y.ls][y.s]
  73. updata(tmp)
  74. if(x.ct < k){
  75. y = {x.ct+, x.ls, x.s};
  76. updata(val)
  77. }
  78. }
  79. }
  80. int a = n&^;
  81. int ans = n+;
  82. for(int j = ; j < sz[a]; j++){
  83. auto &x = vc[a][j];
  84. ans = min(ans, dp[a] dim(x) + bc(All^x.s));
  85. }
  86. printf("Case %d: %d\n\n",++ks,ans);
  87. }
  88. return ;
  89. }

UVA Live Archive 4490 Help Bubu(状压dp)的更多相关文章

  1. UVA 1412 Fund Management (预处理+状压dp)

    状压dp,每个状态可以表示为一个n元组,且上限为8,可以用一个九进制来表示状态.但是这样做用数组开不下,用map离散会T. 而实际上很多九进制数很多都是用不上的.因此类似uva 1601 Mornin ...

  2. 【UVa】Headmaster's Headache(状压dp)

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...

  3. 【UVA】11825 Hackers' Crackdown(状压dp)

    题目 传送门:QWQ 分析 $ n<= 16 $ 显然是状压 然后搞一搞(靠着蓝书yy一下) 代码 #include <bits/stdc++.h> using namespace ...

  4. uva 11825 Hackers&#39; Crackdown (状压dp,子集枚举)

    题目链接:uva 11825 题意: 你是一个黑客,侵入了n台计算机(每台计算机有同样的n种服务),对每台计算机,你能够选择终止一项服务,则他与其相邻的这项服务都终止.你的目标是让很多其它的服务瘫痪( ...

  5. UVa 10817 - Headmaster's Headache(状压DP)

    链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  6. UVA Mega Man's Mission(状压dp)

    把消灭了那些机器人作为状态S,预处理出状态S下可以消灭的机器人,转移统计方案.方案数最多16!,要用64bit保存方案. #include<bits/stdc++.h> using nam ...

  7. UVa 11795 Mega Man's Mission (状压DP)

    题意:你最初只有一个武器,你需要按照一定的顺序消灭n个机器人(n<=16).每消灭一个机器人将会得到他的武器. 每个武器只能杀死特定的机器人.问可以消灭所有机器人的顺序方案总数. 析:dp[s] ...

  8. UVA - 10817 Headmaster's Headache (状压dp+记忆化搜索)

    题意:有M个已聘教师,N个候选老师,S个科目,已知每个老师的雇佣费和可教科目,已聘老师必须雇佣,要求每个科目至少两个老师教的情况下,最少的雇佣费用. 分析: 1.为让雇佣费尽可能少,雇佣的老师应教他所 ...

  9. 状压DP UVA 10817 Headmaster's Headache

    题目传送门 /* 题意:学校有在任的老师和应聘的老师,选择一些应聘老师,使得每门科目至少两个老师教,问最少花费多少 状压DP:一看到数据那么小,肯定是状压了.这个状态不好想,dp[s1][s2]表示s ...

随机推荐

  1. 从零开始安装 Ambari (2) -- 准备本地 repository

    安装 Ambari,最后是为了用它部署 hadoop 集群.安装时默认使用的是 hortonworks 远程的资源,用它部署集群时,需要下载 Hadoop.Hive.HBase 的安装包,速度很慢.我 ...

  2. dbms_xplan的display_cursor查看执行计划

    准备工作: SQL> conn sys/root as sysdba Connected. SQL> grant select on v_$sql_plan to scott; Grant ...

  3. 《算法竞赛进阶指南》1.4Hash

    137. 雪花雪花雪花 有N片雪花,每片雪花由六个角组成,每个角都有长度. 第i片雪花六个角的长度从某个角开始顺时针依次记为ai,1,ai,2,-,ai,6. 因为雪花的形状是封闭的环形,所以从任何一 ...

  4. centos7 yum快速安装php7.1

    1. 安装nginx yum install nginx ##开启nginx service nginx start 2.安装MYSQLyum localinstall http://dev.mysq ...

  5. NppFTP小插件的使用

    大家在Linux系统中配置运行环境时,一定会遇到相关配置文件的修改,虽说在Linux系统中可以使用vi,vim的命令进行文本编辑,但是操作起来还是没有在Windows系统中用的爽,特别是操作大文本量的 ...

  6. Spring 学习(三)AOP

    (1)AOP概述 - AOP:面向切面编程,扩展功能不修改源代码实现 - AOP采取横向抽取机制,取代了传统的纵向继承体系重复性代码 (2)AOP底层原理 原始方法------->纵向继承体系 ...

  7. Storm概念学习系列之storm的特性

    不多说,直接上干货! storm的特性 Storm 是一个开源的分布式实时计算系统,可以简单.可靠地处理大量的数据流. Storm支持水平扩展,具有高容错性,保证每个消息都会得到处理,而且处理速度很快 ...

  8. ZK请求处理

    1. 事务请求转发-事务必须由Leader处理 所有非Leader的服务器收到来自客户端的事务请求,都会将客户端请求已REQUEST形式转发给Leader服务器进行处理 2. 事务处理 Proposa ...

  9. Arduino连接pH计

    关于arduino连接ph,核心的东西就是对ph传感器返回的信号值进行一系列的操作,注意因为返回的信号很弱,而且外部环境对其影响也很大,所以需要在电路设计上加入一些功能,比如信号放大.滤波等,电路设计 ...

  10. vue实现选中列表功能

    <template> <div> <ul v-for="prop in items"> <dt>{{prop.name}}</ ...