题目链接

题意:一天分为N个时间片(可顺到下一天->环形),选择其中B个睡觉。选择第i个时间片能获得u_i点值,但是选择的一个区间内的第一个时间片用来入睡(没睡着),无法获得u_i值。问最大能获得多少u_i值。

第一次做环形dp,本以为按照普通环形方式在数组后面复制一遍即可,但没想到这道题可能就考我们如何不MLE?

代表前i个时间片,睡了j个时间片得到的最大的utility,由于第i个时间片能否起作用取决于上一个时间片有没有选,因此开了第三维代表第i个时间片选了没。 (一开始是设的k代表前一个时间片选没,不易思考)

不选第i个时间片:

前一个时间片没选:dp[i][j][0] = max(dp[i-1][j][0] + 0, dp[i][j][0]);

前一个时间片选了:dp[i][j][0] = max(dp[i-1][j][1] + 0, dp[i][j][0]);

选第i个时间片

前一个时间片没选:dp[i][j][1] = max(dp[i-1][j - 1][0] + 0, dp[i][j][1]);

前一个时间片选了:dp[i][j][1] = max(dp[i-1][j - 1][1] + util[i], dp[i][j][1]);

注意每次转移之前要判断状态合不合法,因为我们初始化不成立的状态为-1,可能会不成立的状态+util[] 导致错误的状态,如果初始化为-INF,只要数据范围不超,应该就不会出现这种问题

然后我们在domjudge上就run error了,赛后交到poj发现是MLE,遂改成类似滚动数组这样,仍然MLE

菜菜的我们为自己状态转移方程正确而感到高兴(〃'▽'〃),但A才是最重要的,嘤嘤嘤

补题:核心是把环形dp转化成两次线性dp。具体如何实现的呢?不考虑环形的话会遗漏一种情况,就是时间片1是睡着了的,所以第二次dp的时候把时间片n和1设置为入睡,具体操作为初始化dp[1][1][1]=utility[1],更新答案的时候只更dp[n&1][b][1]

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=4e3;
const int INF=0x3f3f3f3f;
int dp[2][N][2];
int n,b;
int u[N];
int ans=0;
int main()
{cin>>n>>b;for(int i=1;i<=n;++i)cin>>u[i];memset(dp,-INF,sizeof(dp));dp[0][0][0]=dp[1][1][1]=dp[1][0][0]=0;for(int i=2;i<=n;++i)           //start from 2{int k=i&1;for(int j=1;j<=i;++j){dp[k][j][0]=max(dp[k^1][j][0],dp[k^1][j][1]);dp[k][j][1]=max(dp[k^1][j-1][0],dp[k^1][j-1][1]+u[i]);}}ans=max(dp[n&1][b][0],dp[n&1][b][1]);memset(dp,-INF,sizeof(dp));dp[1][1][1]=u[1];dp[0][0][0]=dp[1][0][0]=0;for(int i=2;i<=n;++i){int k=i&1;for(int j=1;j<=i;++j)       //here{dp[k][j][0]=max(dp[k^1][j][0],dp[k^1][j][1]);dp[k][j][1]=max(dp[k^1][j-1][0],dp[k^1][j-1][1]+u[i]);}}ans=max(ans,dp[n&1][b][1]);cout<<ans<<endl;return 0;}

参考博客

下面是我们2019JSCPC热身赛时敲的代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<set>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const int maxn = 8000;
int k=1;
int dp[2][maxn][2];
int util[maxn];
int cnt=0;int main()
{int n, m;cin >> n >> m;for(int i = 1; i <= n; i++)cin >> util[i];//fill(dp[0][0], dp[0][0] + maxn * maxn * 2, -INF);memset(dp, -1, sizeof(dp));//dp[1][0][0] = 0;//for(int i = 1; i <= 2 * n; i++)dp[0][0][0] = 0;dp[1][0][0]= 0;dp[1][1][1] = 0;for(int i = 1; i <= n; i++)util[i + n] = util[i];//cout << dp[1][1][0] << endl;//cout<<"?"<<endl;for(cnt = 2; cnt <= 2 * n; cnt++){for(int j = 1; j <= cnt; j++){cout << cnt << " " << j << endl;if(dp[k^1][j][0] >= 0){//cout << "if 1:  ";//cout << dp[i][j][0] << " " << dp[i - 1][j][0] << " " ;dp[k][j][0] = max(dp[k^1][j][0] + 0, dp[k][j][0]);//cout << dp[i][j][0] << endl;}if(dp[k^1][j][1] >= 0){//cout << "if 2:  ";//cout << dp[i][j][0] << " " << dp[i - 1][j][1] << " ";dp[k][j][0] = max(dp[k^1][j][1] + 0, dp[k][j][0]);//cout << dp[i][j][0] << endl;}if(dp[k^1][j - 1][0] >= 0){//cout << "if 3:  " ;//cout << dp[i][j][1] << " " << dp[i - 1][j - 1][0] << " ";dp[k][j][1] = max(dp[k^1][j - 1][0] + 0, dp[k][j][1]);//cout << dp[i][j][1] << endl;}if(dp[k^1][j - 1][1] >= 0){//cout << "if 4  ";//cout << dp[i][j][1] << " " << dp[i - 1][j - 1][1] + util[i] << " " ;dp[k][j][1] = max(dp[k^1][j - 1][1] + util[cnt], dp[k][j][1]);//cout << dp[i][j][1] << endl;}}k^=1;}cout << max(dp[(2*n)&1][m][0], dp[(2*n)&1][m][1] ) << endl;return 0;
}

【环形dp】poj 2228 Naptime相关推荐

  1. poj 2228 Naptime(DP的后效性处理)

    \(Naptime\) 描述 Goneril是一只睡眠不足的母牛.她的一天被划分为N(3 <= N <= 3,830)相等的时间段,但她只能在床上花费B(2 <= B <N)不 ...

  2. poj 2228 Naptime

    题目 从N个元素(环形队列)中选出B个,求最大得分.(元素得分仅当其前面的元素也被选择了) 分析 我就不想口胡了 链接 现在知道了处理环上的dp还能这样玩 code #include<iostr ...

  3. POJ 2228. Naptime

    链接 http://poj.org/problem?id=2228 题意 在一天 nnn 个小时中取 bbb 个小时,使权值和最大,bbb 个小时可分成若干段,每段的第一个小时的权值不计入总和,第 n ...

  4. Naptime POJ - 2228

    环形dp 分为两种情况:N休息 N不休息 #include<cstdio> #include<cstring> #include<algorithm> #inclu ...

  5. codevs1085数字游戏(环形DP+划分DP )

    1085 数字游戏  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题目描述 Description 丁丁最近沉迷于一个数字游戏之中.这个游戏看似简单,但丁丁在 ...

  6. poj 2228 环形DP

    题意: 一天有n个时间,有一只牛希望一天可以休息睡小时.如果牛在第i时刻已经熟睡,他可以得到ui的休息.但是如果他在i时刚刚入睡,他不能得到休息.牛可以从前一天晚上睡到第二天.睡觉时间也不一定连续.问 ...

  7. Naptime 【POJ - 2228】

    题目链接 题目大意 有一只牛要休息m个时间段,现在有n个时间段可以供选择,一个时间段有一个睡眠价值,这m个时间段可以连续也可以不连续,每次睡觉的第一个时间段时不获得睡眠价值的,这个牛可以从第一天的晚上 ...

  8. poj2228Naptime——环形DP

    题目:http://poj.org/problem?id=2228 dp[i][j][0/1]表示前i小时中第j小时睡(1)或不睡(0)的最优值: 注意第一个小时,若睡则对最终取结果有要求,即第n个小 ...

  9. P3575-[POI2014]DOO-Around the world【环形dp】

    正题 题目大意:https://www.luogu.org/problemnew/show/P3575 题目大意 一个环,上面有若干个点,若干个询问xxx. 表示上一个降落点和下一个降落点距离不能超过 ...

最新文章

  1. 解决JS在url中传递参数时参数包含中文乱码的问题
  2. java post 打开新页面_JAVA后台POST/GET访问方法
  3. CImage类显示图片
  4. 页面上显示的带有乱码名称的js文件是怎么回事?
  5. Oracle级联查询
  6. 上学的你,是不是最怕老师给家长打电话……
  7. 54 岁的当当李国庆“杀入”区块链!
  8. 苹果watchOS 2引入WatchKit应用,并扩展了硬件支持
  9. Codevs 2800 送外卖(状压DP)
  10. java入门到精通6版pdf_java从入门到精通第6章.pdf
  11. 人生 第一页HTML
  12. 计算机创新课堂教案,1 1.1计算机概述1.2计算机系统课堂教学教案
  13. iozone磁盘读写测试工具的使用以及命令详解、下载(网站最详细讲解步骤)
  14. mysql the cabinet_mysql 一个较特殊的问题:You can’t specify target table ‘wms_cabinet_form’ | 很文博客...
  15. 计算机蓝牙快捷键,电脑蓝牙怎么开,详细教您怎么打开电脑蓝牙
  16. 店铺管理系统是智商税还是真有用?我们替你实测了最火的五个软件!市面上最火的五款店铺管理系统大测评!
  17. 习题8-4 报数 (20分)
  18. python爬虫用到的技术_python爬虫技术的选择
  19. poi在pptx中动态刷新已经存在的图
  20. android hawk 保存map对象,Android Hawk数据库 github开源项目

热门文章

  1. 定时器中断控制LED闪烁(每隔1s)---普中科技开发仪
  2. 自主创新持续领航,麒麟信安荣获“网信自主创新尖峰企业”称号
  3. Dialogue System for Unity文档中英对照版(简雨原创翻译)第四篇(关于主流ui插件拓展相关)
  4. celery爬取58同城二手车数据及若干问题
  5. CMake的一些细节
  6. 2022实体经济寒冬,商家如何通过短视频平台寻找突破口
  7. C# 按Button弹出新的窗体 Show()方法 和 ShowDialog()方法
  8. myeclipse超详细安装教程+图文+安装包获取
  9. python大数据毕业设计题目100例
  10. BZOJ 4605 崂山白花蛇草水 权值线段树+K-D树