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. c# 给文件/文件夹 管理用户权限

    public class PermissionManager { /// <summary> /// 为文件添加users,everyone用户组的完全控制权限 /// </summ ...

  2. 【JZOJ6293】迷宫

    description analysis 有没有想起[\(NOIP2018\)]保卫王国? 设\(tr[t][x][y]\)表示线段树上的\(t\)节点代表的区间,从最左边列的\(x\)行到最右边列\ ...

  3. js--判断当前环境是否为app环境

    /** *判断是否是app环境 */ function getIsApp () { var ua = navigator.userAgent.toLowerCase(); if (ua.match(/ ...

  4. jquery学习笔记(三):事件和应用

    内容来自[汇智网]jquery学习课程 3.1 页面加载事件 在jQuery中页面加载事件是ready().ready()事件类似于就JavaScript中的onLoad()事件,但前者只要页面的DO ...

  5. VS2010-MFC(对话框:字体对话框)

    转自:http://www.jizhuomi.com/software/175.html 字体对话框的作用是用来选择字体.我们也经常能够见到.MFC使用CFontDialog类封装了字体对话框的所有操 ...

  6. STM32笔记——Power Controller(PWR)

    The device requires a 1.8 to 3.6 V operating voltage supply (VDD). An embedded linear voltage regula ...

  7. POJ-2752-Seek the Name-kmp的变形

    The little cat is so famous, that many couples tramp over hill and dale to Byteland, and asked the l ...

  8. QT之QSettings 学习

    1.读写配置文件. 代码如下: //创建配置文件 QSettings iniFile(QCoreApplication::applicationDirPath()+"/test.ini&qu ...

  9. java_缓冲流(字节输出流)

    缓冲流分为: 字节缓冲流:BufferedIntputSream(字节缓冲输出流),BufferdOutputStream(字节缓冲输入流) 字符缓冲流:BufferedReader(字符输入缓冲流) ...

  10. JPA默认方法查询遇到转JSON的处理

    JPA提供的findAll等查询方法在有关联的对象时 比如:在查userInfo @Entity@Table(name = "user_info")public class Use ...