Online JudgeUVA12235

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的更多相关文章

  1. 思维题练习专场-DP篇(附题表)

    转载请注明原文地址http://www.cnblogs.com/LadyLex/p/8536399.html 听说今年省选很可怕?刷题刷题刷题 省选已经结束了但是我们要继续刷题刷题刷题 目标是“有思维 ...

  2. 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 ...

  3. 【思维题 状压dp】APC001F - XOR Tree

    可能算是道中规中矩的套路题吧…… Time limit : 2sec / Memory limit : 256MB Problem Statement You are given a tree wit ...

  4. hdu 5119 (类似于划分数的状态定义) (DP中的计数问题)

    题目描述:求n个数中异或值大于m的方案数有多少个? 设状态f[i][j]代表前i个数异或值为j的方案数有f[i][j]种,那么对于j来说要么选第i个数与前面的i-1个数中的某些数构成j,f[i-1][ ...

  5. [Hdu-5155] Harry And Magic Box[思维题+容斥,计数Dp]

    Online Judge:Hdu5155 Label:思维题+容斥,计数Dp 题面: 题目描述 给定一个大小为\(N*M\)的神奇盒子,里面每行每列都至少有一个钻石,问可行的排列方案数.由于答案较大, ...

  6. [SHOI2007] 书柜的尺寸 思维题+Dp+空间优化

    Online Judge:Luogu-P2160 Label:思维题,Dp,空间优化 题面: 题目描述 给\(N\)本书,每本书有高度\(Hi\),厚度\(Ti\).要摆在一个三层的书架上. 书架的宽 ...

  7. BZOJ 2734 洛谷 3226 [HNOI2012]集合选数【状压DP】【思维题】

    [题解] 思维题,看了别人的博客才会写. 写出这样的矩阵: 1,3,9,... 2,6,18,... 4,12.36,... 8,24,72,... 我们要做的就是从矩阵中选出一些数字,但是不能选相邻 ...

  8. 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个工程,每个需要某 ...

  9. 状态压缩dp增量统计贡献——cf1238E(好题)

    这题的状态设计非常巧妙,因为dp[S]表示的并非当前正确的值,而是维护一个中间量,这个中间量在到达末状态时才正确 当然官方的题解其实更加直观,只不过理解起来其实有点困难 /* 给定一个串s,字符集为2 ...

随机推荐

  1. sql (5) 左右连接

    左连接 SQL LEFT JOIN LEFT JOIN 关键字会从左表 (table_name1) 那里返回所有的行,即使在右表 (table_name2) 中没有匹配的行.语法SELECT colu ...

  2. vagrant centos lamp小记

    更新包 sudo yum -y update vagrant centos 默认语言好像是德语,看不懂,需要更换为 en_US [vagrant@localhost ~]$ locale LANG=d ...

  3. leetcood学习笔记-45-跳跃游戏二

    题目描述: 第一次提交;超时 class Solution: def jump(self, nums: List[int]) -> int: l = [] for i in range(len( ...

  4. linux上给其他在线用户发送信息(wall, write, talk, mesg)

        linux上给其他在线用户发送信息(wall, write, talk, mesg)   2018-01-05 lonskyMR 转自 恶之一眉 修改 微信分享: 设置登录提示     /et ...

  5. matlab中乘法和点乘以及除法和点除的联系是什么?

    一,*和.*的联系和区别. 1,在进行数值运行和数值乘矩阵,这两种没有区别,例如:a*b=a.*b; a*B=a.*B; B*a=B.*a (其中小写字母表示数值,大写字母表示矩阵,下同). 2,在处 ...

  6. C/C++ Microsoft Visual Studio c++ DOC Home

    { // https://docs.microsoft.com/zh-cn/cpp/overview/visual-cpp-in-visual-studio?view=vs-2017 // https ...

  7. POJ 2104:K-th Number 整体二分

    感觉整体二分是个很有趣的东西. 在别人的博客上看到一句话 对于二分能够解决的询问,如果有多个,那么如果支持离线处理的话,那么就可以使用整体二分了 树套树写了一天还是WA着,调得焦头烂额,所以决定学cd ...

  8. Django static静态配置文件

    对于Django来说静态文件一般交由Web服务器处理,Django本身不处理静态文件.为了使Django开发环境能够处理静态文件,Django有和生产环境不同的静态文件配置方式. Django 版本: ...

  9. artTemplate不仅可以在浏览器中使用,还可以在node中使用

    artTemplate不仅可以在浏览器中使用,还可以在node中使用 浏览器中引入lib/template-web.js node中  var  template = require(‘art-tem ...

  10. bat删除多少天前的文件包含子目录

    通过 Forfiles 删除指定目录下过期的备份文件 /*-- 用法详解 D:/>forfiles /? FORFILES [/P pathname] [/M searchmask] [/S] ...