hihoCoder #1044 : 状态压缩·一 (清垃圾)
题意:
某车厢有一列座位,共有n个位置,清洁工要在这n个位置上清垃圾,但是不能全部位置都清理,只能选择部分。选择的规则是,连续的m个位置内,不能够清理超过q个,也就是说从第1~m个位置最多可以清q个,清q+1个就不行了。当然,q一般是小于m的,不然岂不是可以m个位置全清了?那就没限制了。
思路:
看小hi小ho讲的完全是一知半解,看了大神的代码一整天才看懂意思。下面做分析(以我能理解的角度,以及通俗的角度,方便回忆。):
三个变量的定义:
n: 一共有n个座位。
m: 在m个连续的座位。
q:最多可以清扫的位置个数。
w[1~n]: 分别对应n个位置上的垃圾数量。(ps:垃圾肯定有多有少,才需要进行决策计算,不然只需要保证m个位置内有q个就行了,q个位置可以随便选)
问题的分析:
(1)这不是背包!相同点:都是n个东西,每次多考虑一个。不同点:背包有容量限制可以作为列数进行dp,而这里没有(也就不能开一个二维数组了),却给出了位置的数量方面的限制。
(2)既然要用动态规划,那就要从小问题开始考虑,而较大问题要依靠较小的问题来进行决策计算。小问题:最小就是只有1个位置了。每次考虑的增加规模量:每次多考虑1个位置,直到n个全考虑了。
(3)假如m=n,那简单了,问题转成:在n个位置上选出q个,使得垃圾的总数量最多。穷举:2^n种可能,这里边还要去掉一些位置个数大于q的(大于q就是非法),剩下来的才是所有的可能(只是垃圾量的问题,都是合法的)。
(4)假如n>m,那麻烦了。我们先在前m个进行决策(也就是第3所分析的一样),那么第m+1个应该考虑2~m这里面有没有达到q,达到了,那就只能不清理了;若没有达到,那还可以选择清or不清。为什么会有选择不清的情况?有得清还不赶紧清了吗?原因是,如果你这一步选择清理了,那第m+2个位置就要考虑从3到m+1的位置上有没有达到q,达到了,这一步又肯定没得选择了。假设只有m+2个,前面1~m个位置上已经决策完成,而第m+1个位置上的垃圾极少,第m+2个位置上的垃圾超多,由于在前3~m个位置上的决策只是选了q-1个,但是你在第m+1个位置上选择了清理,那么第m+2个位置上的超多垃圾清不到了。
(5)结论是:每一次决定第i个位置清or不清理,靠的是前面m-1个位置上的清理数量,跟超过m-1个的都没有任何关系。前面穷举的结果在符合规则的条件下不影响后面的决策,你仍可选择不清理。
关于实现:
(1)肯定是个二维数组来保存状态,数组中保存什么?肯定是第i行(包括)之前所做出的决定所清理的垃圾总量。那列是什么?是第i行(包括)之前m个位置上是否清理的信息。考虑到m<=10,那么十位的二进制最多能表达1023,这就是数组列的上限。那么dp[i][j]表示:前 i 个位置在 j (1的个数信息)这种决策情况下所能获得的最大垃圾量。
(2)看个例子:n有{1, 2, 3, 4, 5, 6, 7, 8, 9}共9个位置,m限制为5,上限q为3。
{1, 2, 3, 4, 5, , 7, 8, 9} //假设1~5已经考虑完了。准备考虑第6个
{1, 2, 3, 4, 5, 6, 7, 8, 9} //考虑6不需要关心1了。而d[6][j]记录的是1~6的的所决定清理的垃圾量,而j只用5个位来表示2~6的存放情况。假设j={10101}b二进制.也就是第2,4,6位置上决定了清理,那么dp[6][j]=" w[] " + w[2]+w[4]+w[6]。这红色的w[]代表第1个的决策结果,具体清没清理,得从dp[5][j>>1]和dp[5][(j>>1)+(1<<5)]看谁大来决定了,小的那个没有必要保存了,1~5的垃圾量明显会比别人小,先淘汰了。
(3)看代码吧~注释都够能理解的了。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N=;
int w[N]; //权值
int dp[][N]; //只需要两行就够了,每次计算都要切换到另一行。
int cn[N]={, , }; //提前计算好对于任意一个j里面所含的1的个数。
int n, m, q;
const int b[]={, , , , , , , , , , }; //提前计算好M个二进制所能表示的数字的上限。
/*
int cnt(int j) //还可以用这种方法来统计j的二进制中含1的个数。慢了一些。
{
int maxn=0;
while(j)
{
if(j&1)
maxn++;
j>>=1;
}
return maxn;
}
*/
int main()
{
//freopen("input.txt", "r", stdin);
//提前计算好2^m种可能,所产生的1的个数,就不用每次都要数了。
for (int i=; i<b[]; ++i)
cn[i] =cn[i>>] +cn[i&]; //这里还用到了分治法,每个值的计算还依靠于比其更小规模的结果。 while(cin>>n>>m>>q)
{
memset(dp, , sizeof(dp));
for(int i=; i<=n; i++)
cin>>w[i];
//核心在这,计算所有可能产生的序列,所产生的最大垃圾量。
int tmp = <<m; //上限
for(int i=; i<=n; i++)
for(int j=; j<tmp; j++)
if( cn[j]<=q ) //前m个位置选择清理的位置数量小于等于q。
dp[i&][j]=max( dp[~i&][j>>], dp[~i&][(j>>)+b[m-]] ) + (j&)*w[i]; //i的决策由j的最后一位表示。
//最大垃圾量可能存在于任何排列中,所以要全扫一遍才知道。
int ans=;
for(int i=; i<tmp; i++)
ans=max(ans, dp[n&][i]);
cout<<ans<<endl;
}
return ;
}
AC代码
hihoCoder #1044 : 状态压缩·一 (清垃圾)的更多相关文章
- [hihoCoder] #1044 : 状态压缩·一
时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho在兑换到了喜欢的奖品之后,便继续起了他们的美国之行,思来想去,他们决定乘坐火车前往下一座城市——那座城市即将 ...
- hihoCoder 1044 : 状态压缩·一 状压dp
思路:状态压缩,dp(i, j)表示考虑前i个数且[i-m+1, i]的选择情况为j.如果要选择当前这个数并且,数位1的个数不超过q,则dp[i+1][nex] = max(dp[i+1][nex], ...
- hihocoder #1044 : 状态压缩·一 状压DP
http://hihocoder.com/problemset/problem/1044 可以看出来每一位的选取只与前m位有关,我们把每个位置起始的前m位选取状态看出01序列,就可以作为一个数字来存储 ...
- hiho 1044 : 状态压缩
#1044 : 状态压缩·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho在兑换到了喜欢的奖品之后,便继续起了他们的美国之行,思来想去,他们决定乘坐火车 ...
- hiho #1044 : 状态压缩·一
描述 小Hi和小Ho在兑换到了喜欢的奖品之后,便继续起了他们的美国之行,思来想去,他们决定乘坐火车前往下一座城市——那座城市即将举行美食节! 但是不幸的是,小Hi和小Ho并没有能够买到很好的火车票—— ...
- hihoCoder week8 状态压缩·一
状态压缩 写了两个半小时 太菜了 题目链接 https://hihocoder.com/contest/hiho8/problem/1 #include <bits/stdc++.h> ...
- hihoCoder#1048 状态压缩·二
原题地址 位运算的状态压缩太操蛋了,很容易出错...又是数组没开够导致诡异现象(明明某个值是1,莫名其妙就变成0了),害我debug一整天!fuck 代码: #include <iostream ...
- HihoCoder第八周:状态压缩 一
1044 : 状态压缩•一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho在兑换到了喜欢的奖品之后,便继续起了他们的美国之行,思来想去,他们决定乘坐火车前 ...
- HihoCoder 1044 垃圾清理 (优化:状态压缩)
状态压缩·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho在兑换到了喜欢的奖品之后,便继续起了他们的美国之行,思来想去,他们决定乘坐火车前往下一座城市— ...
随机推荐
- Sharepoint商务智能学习笔记之PowerPviot Service安装与配置(七)
1) PowerPviot Service多服务器部署注意事项 PowerPviot Service不是Sharepoint自带的服务,要想使用PowerPviot Service需要先在sharep ...
- IDEA的git密码修改
问题: 如果你办公的电脑是同事用过,在每次提交git的时候都显示是他的名字.想要修改提交git用户名密码. 但是博客idea 修改Git密码和账号方法所示方法无效.且操作系统是win10.(其他操作系 ...
- luoguP4389 付公主的背包
luogu 显然这是个背包题 显然物品的数量是不用管的 所以考虑大小为\(v\)的物品可以装的体积用生成函数表示一下 \[ f(x)=\sum_{i=0}^{+\infty}x^{vi}=\frac{ ...
- 关于php命名空间的理解
以phpmailer这个类库为例,composer自动加载好该类库,有用的文件都放在src这个目录下 这些文件的命名空间都是这个:namespace PHPMailer\PHPMailer; 如果我们 ...
- 原生JS轮播-各种效果的极简实现(二)面向对象版本的实现和优化
之前写了一篇原生JS轮播,不过是非面向对象的,并且也没有添加上自动轮播.这里来写一下如何优化和进阶. 这里简单地介绍一下之前的代码,这是html结构 <body> <div clas ...
- Django 04 模板标签(if、for、url、with、autoeacape、模板继承于引用、静态文件加载)
Django 04 模板标签(if.for.url.with.autoeacape.模板继承于引用.静态文件加载) 一.if.for.url.with.autoescape urlpatterns = ...
- 使用spring boot admin
spring boot admin管理端, 需要部署成独立的应用 pom中添加依赖 <dependency> <groupId>de.codecentric</group ...
- calendar 类 用法
add()和roll()区别 一.Calendar 月份从 0-11,要表示8月,应该传入7 . 二.set() 会自动转换为合法的日期,如 set(1999,8,31) 表示的是1999-09-3 ...
- ERROR [org.apache.hadoop.util.Shell] - Failed to locate the winutils binary in the hadoop binary path
错误日志如下: -- ::, DEBUG [org.apache.hadoop.metrics2.lib.MutableMetricsFactory] - field org.apache.hadoo ...
- arch安装软件提示包损坏
错误:lib32-libjpeg6-turbo: signature from "Colin Keenan <colinnkeenan@gmail.com>" is u ...