LA 4327 Parade(单调队列优化dp)
题目链接:
题目大意(摘自刘汝佳<<算法竞赛入门经典--训练指南>>):F城是由n+1条横向路和m+1条竖向路组成。你的任务是从最南边的路走到最北边的路,使得走过的路上的高兴值和最大(注意,一段路上的高兴值可能是负数)。同一段路不能经过两次,且不能从北往南走,另外,在每条横向路上所花的时间不能超过k。求从南到北走完可以获得的最大高兴值。
分析:用dp[i][j]表示到达编号为(i,j)的路口时所能得到的最大高兴值,则dp[i][j] = max{ dp[i+1][j]; dp[i+1][k] + s[i+1][j]-s[i+1][k], (L[i][j] <= k < j); dp[i+1][k] + s[i+1][k]-s[i+1][j], (j <= k < R[i][j]) };
其中,s[i][j] 表示第i行从第0个路口到第j个路口的高兴值之和,L[i][j]是同一行上能够走到(i,j)位置的最左位置,R[i][j]是同一行上能够走到(i,j)位置的最右位置,这三个量都可以预处理出来。
上述dp的复杂度是O(n^3)的,需要优化,考虑dp[i][j] = max(dp[i+1][k] + s[i+1][j]-s[i+1][k]),i,j固定时,s[i+1][j]为常量,不妨设s[i+1][j] = P, 且令f[k] = dp[i+1][k] - s[i+1][k],则dp[i][j] = max(f[k]) + P,此时就可以用单调队列来维护了,对于每行,从左到右扫描,并维护一个递减的单调对列。具体参看代码。
#include <cstdio>
#include <algorithm>
using namespace std;
#define N 104
#define M 10004 int L[N][M], R[N][M];
int v[N][M], t[N][M];
int n, m, k;
int Q[M];
int f[M], sum[N][M], dp[N][M];
int main()
{
while(~scanf("%d %d %d", &n, &m, &k), n||m||k)
{
for(int i = ; i <= n+; i++)
for(int j = ; j < m; j++)
scanf("%d", &v[i][j]);
for(int i = ; i <= n+; i++)
for(int j = ; j < m; j++)
scanf("%d", &t[i][j]);
for(int i = ; i <= n+; i++)
{
sum[i][] = ;
for(int j = ; j <= m; j++) sum[i][j] = sum[i][j-] + v[i][j-];
}
for(int i = ; i <= n+; i++)
{
L[i][] = , R[i][m] = m;
int cur = , id = ;
for(int j = ; j <= m; j++){
cur += t[i][j-];
while(cur > k) cur -= t[i][id++];
L[i][j] = id;
}
cur = , id = m-;
for(int j = m-; j >= ; j--){
cur += t[i][j];
while(cur > k) cur -= t[i][id--];
R[i][j] = id+;
}
} for(int i = ; i < m+; i++) dp[n+][i] = ;
for(int i = n; i >= ; i--)
{
int head = , rear = ;
for(int j = ; j < m+; j++)
{
f[j] = dp[i+][j] - sum[i+][j];
while(rear < head && Q[rear] < L[i+][j]) rear++;
while(head > rear && f[j] >= f[Q[head-]]) head--;
Q[head++] = j;
dp[i][j] = max(dp[i+][j], sum[i+][j]+f[Q[rear]]);
}
head = , rear = ;
for(int j = m; j >= ; j--)
{
f[j] = dp[i+][j] + sum[i+][j];
while(rear < head && Q[rear] > R[i+][j]) rear++;
while(head > rear && f[j] >= f[Q[head-]]) head--;
Q[head++] = j;
dp[i][j] = max(dp[i][j], f[Q[rear]]-sum[i+][j]);
}
}
int ans = ;
for(int i = ; i < m+; i++) ans = max(ans, dp[][i]);
printf("%d\n", ans);
}
return ;
}
LA 4327 Parade(单调队列优化dp)的更多相关文章
- Parade(单调队列优化dp)
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2490 Parade Time Limit: 4000/2000 MS (Java/Others) ...
- 「学习笔记」单调队列优化dp
目录 算法 例题 最大子段和 题意 思路 代码 修剪草坪 题意 思路 代码 瑰丽华尔兹 题意 思路 代码 股票交易 题意 思路 代码 算法 使用单调队列优化dp 废话 对与一些dp的转移方程,我们可以 ...
- 单调队列优化DP,多重背包
单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...
- bzoj1855: [Scoi2010]股票交易--单调队列优化DP
单调队列优化DP的模板题 不难列出DP方程: 对于买入的情况 由于dp[i][j]=max{dp[i-w-1][k]+k*Ap[i]-j*Ap[i]} AP[i]*j是固定的,在队列中维护dp[i-w ...
- hdu3401:单调队列优化dp
第一个单调队列优化dp 写了半天,最后初始化搞错了还一直wa.. 题目大意: 炒股,总共 t 天,每天可以买入na[i]股,卖出nb[i]股,价钱分别为pa[i]和pb[i],最大同时拥有p股 且一次 ...
- BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP
BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP Description 有一排n棵树,第i棵树的高度是Di. MHY要从第一棵树到第n棵树去找他的妹子玩. 如果MHY在 ...
- 【单调队列优化dp】 分组
[单调队列优化dp] 分组 >>>>题目 [题目] 给定一行n个非负整数,现在你可以选择其中若干个数,但不能有连续k个数被选择.你的任务是使得选出的数字的和最大 [输入格式] ...
- [小明打联盟][斜率/单调队列 优化dp][背包]
链接:https://ac.nowcoder.com/acm/problem/14553来源:牛客网 题目描述 小明很喜欢打游戏,现在已知一个新英雄即将推出,他同样拥有四个技能,其中三个小技能的释放时 ...
- 单调队列以及单调队列优化DP
单调队列定义: 其实单调队列就是一种队列内的元素有单调性的队列,因为其单调性所以经常会被用来维护区间最值或者降低DP的维数已达到降维来减少空间及时间的目的. 单调队列的一般应用: 1.维护区间最值 2 ...
随机推荐
- Octavia health-manager 与 amphora 故障修复的实现与分析
目录 文章目录 目录 Health Manager 监控 amphora 健康状态 故障转移 故障迁移测试 Health Manager Health Manager - This subcompon ...
- 简要介绍一下MD5加密的书写
大家应该多清楚数据的重要性,可以假设一下:一个非常大的企业,因为一个程序员的疏忽大意,没有使用MD5加密,那么可以说这个企业的数据库是非常不安全的,可以轻而易举的的访问你的数据库,并执行任何操作. 下 ...
- String.prototype.replace
第一个参数是正则表达式 第二个参数是一个replacer 函数的入参如下: replacer(match,p1,p2,p3.. 其实也相当于 replacer($&,$1,$2,$3.. 资料 ...
- 阶段3 1.Mybatis_03.自定义Mybatis框架_3.自定义mybatis的编码-根据测试类中缺少的创建接口和类
先认识一下这几个类.Resources是一个class SqlSessionFactoryBuilder 创建新项目 复制相关的依赖 复制之前的代码 复制到当前项目的src下 把Mybits的依赖删除 ...
- 网易云课堂_C++程序设计入门(下)_第7单元:出入虽同趣,所向各有宜 – 文件输入和输出_第7单元 - 作业2:编程互评
第7单元 - 作业2:编程互评 查看帮助 返回 提交作业(剩余10天) 完成并提交作业 作业批改 互评训练 互评作业 自评作业 成绩公布 查看成绩 由于在线编程不支持 ...
- UVA11987 带删除并查集
1~n,n个数,初始每个数独自作为一个集合,然后进行m次操作.操作有三种:1 p q :把 p 所在的集合合并到 q 所在的集合 2 p q :把 p 从 p 的集合中拿出,放到 q 的集合里 3 p ...
- Rocketmq-概念
一.Rcoketmq Rocketmq是一个消息中间件,简单来说就是传递消息用的. 二.Rocketmq构成 1.Rocketmq组件不是单个的软件,它是由四个组件构成的: (1)Producer 消 ...
- JSP技术学习总结
1.JSP的执行过程 首先用户向服务器发出请求,服务器在接收请求后去寻找响应的jsp页面,然后服务器将jsp页面翻译成.java文件,然后进行编译得到.class字节码文件,服务器执行class文件将 ...
- C++中的函数重载分析(一)
1,重载是 C 语言到 C++ 语言的一个飞跃,C 语言中没有重载的概念,所有的函数 名是不允许有重复的,在 C++ 中因为引进了重载,所以函数名可以重复: 2,自然语言中的上下文: 1,你知道上面词 ...
- thinkPHP三级城市联动
html+js: <!doctype html> <html lang="en"> <head> <meta charset=" ...