题目大意:有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的更多相关文章

  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. 数细胞-swust oj

    数细胞(0964) 一矩形阵列由数字0到9组成,数字1到9代表细胞,细胞的定义为沿细胞数字上下左右还是细胞数字则为同一细胞,求给定矩形阵列的细胞个数.编程需要用到的队列及其相关函数已经实现,你只需要完 ...

  2. 11个优秀的Android开发开源项目

    一. 一个类似微信的时光轴效果   时光轴效果 项目地址 https://github.com/ljtyzhr/TimeLine 二. 安卓选择器类库,包括日期.时间.单项.双项选择器.城市地址选择器 ...

  3. Spring集成Redis缓存

    作者:13 GItHub:https://github.com/ZHENFENG13 版权声明:本文为原创文章,未经允许不得转载. 整合Redis 本来以为类似的Redis教程和整合代码应该会很多,因 ...

  4. 分布式版本控制系统 Git 教程

    简介 Git 是什么? Git 是一个开源的分布式版本控制系统. 什么是版本控制? 版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统. 什么是分布式版本控制系统? 介绍分布 ...

  5. Java数据结构和算法(七)——链表

    前面博客我们在讲解数组中,知道数组作为数据存储结构有一定的缺陷.在无序数组中,搜索性能差,在有序数组中,插入效率又很低,而且这两种数组的删除效率都很低,并且数组在创建后,其大小是固定了,设置的过大会造 ...

  6. msf入门学习笔记

    msf-------------------------------------- service postgresql startservice metasploit startmsfconsole ...

  7. win10 mysql详尽安装教程

    我的电脑系统是win10 64位系统 我安装mysql不下5次,装好了又卸,卸了又装,看了老多篇文章和博客,非常感谢博主的无私帮助,以下是这些博主的文章: https://www.cnblogs.co ...

  8. 【NOIP2015提高组】运输计划

    https://daniu.luogu.org/problem/show?pid=2680 使完成所有运输计划的时间最短,也就是使时间最长的运输计划耗时最短.最大值最小问题考虑用二分答案,每次chec ...

  9. Codeforces 830C On the Bench

    题意:给你n个数,问有多少种排列方式使得任意两个相邻的数的乘积都不是完全平方数 我好弱,被组合和数论吊着打... 首先我们可以把每个数中固有的完全平方数给分离出来,那么答案其实就只与处理后的序列相关. ...

  10. window.open()被拦截问题

    最近做项目的时候遇到一个需求,在商品详情页面中点击购买按钮,之后再新标签页中打开生成的订单页面,所以想用window.open()来实现.但是测试的时候发现打开的链接被浏览器拦截. 之后,开始在网上查 ...