【题解】Acting Cute
题目
测试地址:POJ2228,USACO 2005 January Gold。
题目来源:USACO 2005 January Gold / 模拟赛 T2(本题题面)。
题目描述
正在 rainbow 的城堡游玩的 Freda 恰好看见了在地毯上跳舞卖萌的水叮当……于是……
Freda:“呜咕>_< 我也要卖萌T_T!”
rainbow 给了 Freda \(N\) 秒的自由活动时间,不过由于刚刚游览城堡有些累了,Freda 只想花 \(B\) 秒的时间来卖萌,剩下的时间她要在 rainbow 的城堡里睡个好觉好好休息一下。
rainbow 给这 \(N\) 秒每秒定义了一个值 \(U_i\),如果第 \(i\) 秒钟 Freda 在卖萌,那么她可以获得 \(U_i\) 点卖萌指数lala~
Freda 开始卖萌后可以随时停止,休息一会儿之后再开始。不过每次 Freda 开始卖萌时,都需要 \(1\) 秒来准备= =,这一秒是不能获得卖萌指数的。当然,Freda 卖萌和准备的总时间 不能超过 \(B\)。
更特殊的是,这 \(N\) 秒钟时间是 环形 的。也就是 Freda 可以从任意时间开始她的自由活动并持续 \(N\) 秒。
为了使自己表现得比水叮当更萌,现在 Freda 想知道,她最多能获得多少卖萌指数呢?
输入格式
第一行包含两个整数 \(N\) 和 \(B\)。
第 \(2\)~\(N+1\) 行每行一个整数,其中第 \(i+1\) 行的整数表示 \(U_i\)。
输出格式
输出一个整数,表示 Freda 可以获得的最大卖萌指数。
数据范围
各个测试点时间限制 \(1\mathrm{s}\),空间限制 \(1\mathrm{GiB}\)。
- 对于 \(60\%\) 的数据,\(N\leq 100\)
- 对于 \(100\%\) 的数据,\(0\leq B\leq N\leq 3600\),\(0\leq U_i\leq 200000\)。
分析
这道题可以看出来是 \(\mathtt{DP}\),只不过环形这个条件比较难搞。
线性情况
状态定义和递推
先考虑线性的情况,定义 \(f_{i,j}\) 为前 \(i\) 分钟已经卖萌 \(j\) 分钟的卖萌指数最大值。
则可以得到:(\(val(i,j)\)代表从 \(i\) 时刻到 \(j\) 时刻的卖萌指数)
\]
在这个基础上,我们发现这个算法的复杂度是 \(\Theta(n^3)\) 的,只能通过部分分。如何优化?
优化
首先,\(val(i,j)\) 是可以通过前缀和实现 \(\Theta(1)\) 的(设前缀和数组为\(\{pref_i\}\))。接下来考虑 \(\max_{0< k\leq j}\{f_{i-k,j-k}\}\)
考虑数列 \(l_{k,u} = \max_{k\leq t\leq u}\{f_{t,t-k}-pref_{t+1}\}\),则 \(\max_{0< k\leq j}\{f_{i-k,j-k}\}\) 就是 \(l_{i-j,i-1}+pref_i\)。
每次计算出 \(f_{i,j}\) 后,可以 \(\Theta(1)\) 更新 \(l_{i-j,i}\),这样就可以将复杂度降至 \(\Theta(n^2)\)。
同时 \(l_{k,u}\) 可以简化成 \(l_k\),节省空间。(虽然这道题有的是空间)
上代码:
for (int i = 1; i <= n; i++)
for (int j = 0; j <= i && j <= lim; j++)
{
dp[i][j] = ab_max(dp[i-1][j], ln[i-j] + pref[i]);
if (i != n)
ln[i-j] = ab_max(ln[i-j], dp[i-1][j] - pref[i+1]);
}
环形情况
既然线性情况 Get,那么环形又如何处理呢?
对于最优情况,首先考虑这几个结论:
- 卖萌结束后的下一分钟,卖萌必然不开始。
为什么?如果下一分钟开始了,这一分钟的卖萌指数就无法算入。但是如果将这一分钟连上上一分钟的卖萌,这一分钟的卖萌指数就能算入。
考虑到 \(U_i \geq 0\),所以算上一定 不差于 不算上。
- 线性与环形的唯一差别就是第 \(1\) 分钟有没有卖萌 (不是准备)。
为什么?因为如果第 \(1\) 分钟没有卖萌或在做准备,则与线性的某种情况等价。
唯一要考虑的环形情况就是有跨越的卖萌时间段。
所以,我们再进行一遍 \(\mathtt{DP}\)。只不过这一次 \(\mathtt{DP}\) 强制要求第 \(1\) 分钟正在卖萌,而且从某一时刻到第 \(n\) 分钟一直在卖萌(有准备)。
为了思路清晰,这次使用 \(revdp_{i,j}\) 进行记录。
上代码:
memset(ln, 0xcf, sizeof(ln));
revdp[0][0] = revdp[1][0] = 0;
ln[0] = -pref[1]; // 注意初始化
revdp[0][0] = 0;
for (int i = 1; i <= lim; i++)
revdp[i][i] = pref[i];
for (int i = 1; i < n; i++)
for (int j = 0; j < i && j <= lim; j++)
{
revdp[i][j] = ab_max(revdp[i-1][j], ln[i-j] + pref[i]);
ln[i-j] = ab_max(ln[i-j], revdp[i-1][j] - pref[i+1]);
}
for (int i = 0; i <= lim; i++)
revdp[n][i] = ln[n-i] + pref[n];
最后只需要在 \(dp_{n,b}\) 和 \(revdp_{n,b}\) 中选择一个最小值就行了。
Code
#include <cstdio>
#include <cstring>
using namespace std;
const int max_n = 3600;
int pref[max_n+1], dp[max_n+1][max_n+1], ln[max_n+1], revdp[max_n+1][max_n+1] = {};
inline int ab_max(int x, int y) { return (x > y)? x:y; }
int main()
{
memset(dp, 0xcf, sizeof(dp));
memset(revdp, 0xcf, sizeof(revdp));
memset(ln, 0xcf, sizeof(ln));
dp[0][0] = dp[1][0] = 0;
int n, lim, tmp;
scanf("%d%d", &n, &lim);
if (lim <= 1)
{
puts("0");
return 0;
}
pref[0] = 0;
for (int i = 0; i < n; i++)
{
scanf("%d", &tmp);
pref[i+1] = pref[i] + tmp;
}
ln[0] = -pref[1];
for (int i = 1; i <= n; i++)
for (int j = 0; j <= i && j <= lim; j++)
{
dp[i][j] = ab_max(dp[i-1][j], ln[i-j] + pref[i]);
if (i != n)
ln[i-j] = ab_max(ln[i-j], dp[i-1][j] - pref[i+1]);
}
memset(ln, 0xcf, sizeof(ln));
revdp[0][0] = revdp[1][0] = 0;
ln[0] = -pref[1];
revdp[0][0] = 0;
for (int i = 1; i <= lim; i++)
revdp[i][i] = pref[i];
for (int i = 1; i < n; i++)
for (int j = 0; j < i && j <= lim; j++)
{
revdp[i][j] = ab_max(revdp[i-1][j], ln[i-j] + pref[i]);
ln[i-j] = ab_max(ln[i-j], revdp[i-1][j] - pref[i+1]);
}
for (int i = 0; i <= lim; i++)
revdp[n][i] = ln[n-i] + pref[n];
printf("%d\n", ab_max(dp[n][lim], revdp[n][lim]));
return 0;
}
备注
标算使用的定义是 \(f_{i,j,k}\) 为前 \(i\) 分钟共卖萌 \(j\) 分钟,第 \(i\) 分钟的状态为 \(k\) 时的最大卖萌指数。
则状态转移就是 \(f_{i,j,k}=\begin{cases}\max_{u=0,1}\{f_{i-1,j,u}\}&k=0\\\max\{f_{i-1,j-1,0},f_{i-1,j-1,1}+U_i\}\}&k=1\end{cases}\)
至于具体的细节,供读者思考。(明明是 5ab 太菜了,想不出来)
【题解】Acting Cute的更多相关文章
- Poetize6: Acting Cute
3042: Acting Cute Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 59 Solved: 36[Submit][Status] Des ...
- BZOJ ac100题存档
不知不觉AC100题了,放眼望去好像都是水题.在这里就做一个存档吧(特别感谢各位大神尤其是云神http://hi.baidu.com/greencloud和丽洁姐http://wjmzbmr.com/ ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- 越狱Season 1-Episode 4: Cute Poison
Season 1, Episode 4: Cute Poison [Previously on Prison Break] previously: 以前地 前情提要 -Burrows: I didn' ...
- Codeforces Round #447 (Div. 2) 题解 【ABCDE】
BC都被hack的人生,痛苦. 下面是题解的表演时间: A. QAQ "QAQ" is a word to denote an expression of crying. Imag ...
- CodeChef November Challenge 2013 部分题解
http://www.codechef.com/NOV13 还在比...我先放一部分题解吧... Uncle Johny 排序一遍 struct node{ int val; int pos; }a[ ...
- 2016女生专场 ABCDEF题解 其他待补...
GHIJ待补... A.HUD5702:Solving Order Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/3276 ...
- Codeforces Round#630 div2 A~C题解
...
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
随机推荐
- Go语言 | 哪些大公司在用go语言?
Go大概09年面世以来,已经8年了,也算是8年抗战.在这8年中,已经有很多公司开始使用Go语言开发自己的服务,甚至完全转向Go开发,也诞生了很多基于Go的服务和应用,比如Dokcer.k8s等,现在我 ...
- Kubernetes 二进制部署(二)集群部署(多 Master 节点通过 Nginx 负载均衡)
0. 前言 紧接上一篇,本篇文章我们尝试学习多节点部署 kubernetes 集群 并通过 haproxy+keepalived 实现 Master 节点的负载均衡 1. 实验环境 实验环境主要为 5 ...
- vim的几种模式
Normal Mode 普通模式 功能:在这种模式下可以移动光标等. 进入:默认进入vim之后,处于这种模式.在其他模式下狂按ESC后进入此模式. Visual Mode 可视模式 功能:在这种模式下 ...
- 装系统:Win7,机子是Dell 5460,有半高的mSATA SSD
问题描述:Dell Vostro 5460有一个机械盘,有一个半高的mSATA SSD,现在想将系统重装到mSATA SSD上,但是机子BIOS的Boot选项没有mSATA,只有机械盘,怎么办? 解决 ...
- 初级入门 --- 认识 WebGL
WebGL 是什么? WebGL 是一组基于 JavaScript 语言的图形规范,浏览器厂商按照这组规范进行实现,为 Web 开发者提供一套3D图形相关的 API. 这些 API 能够让 Web 开 ...
- 请求http协议分析- (mysql-thinkphp) (5)
http协议 https://tools.ietf.org/pdf/rfc7231.pdf https://www.w3.org/Protocols/ ======================== ...
- Readiness 探测【转】
除了 Liveness 探测,Kubernetes Health Check 机制还包括 Readiness 探测. 用户通过 Liveness 探测可以告诉 Kubernetes 什么时候通过重启容 ...
- 201707《Ruby元编程》
元编程不过是编程--经典必读 作用域(绑定) 打破作用域门的方式 对象模型图 七条规则 法术手册 作用域(绑定) 改变作用域的关键字, 分别是module,class和def.我们称为作用域的门(sc ...
- ROS学习笔记2-基本概念
本笔记来源于:http://wiki.ros.org/ROS/Concepts ROS文件系统级别文件系统级别主要包含了你能在ROS的磁盘上遇到的资源,包括: 包(Packages):包是ROS中资源 ...
- spingboot2.0外部引入xml配置文件时找不到文件等报错
之前的项目可以启动,后面不知道为什么都不行了,报错如下: SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found bindin ...