题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2490

Parade

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 902    Accepted Submission(s): 396

Problem Description
Panagola,
The Lord of city F likes to parade very much. He always inspects his
city in his car and enjoys the welcome of his citizens. City F has a
regular road system. It looks like a matrix with n+1 west-east roads and
m+1 north-south roads. Of course, there are (n+1)×(m+1) road crosses in
that system. The parade can start at any cross in the southernmost road
and end at any cross in the northernmost road. Panagola will never
travel from north to south or pass a cross more than once. Citizens will
see Panagola along the sides of every west-east road. People who love
Panagola will give him a warm welcome and those who hate him will throw
eggs and tomatoes instead. We call a road segment connecting two
adjacent crosses in a west-east road a “love-hate zone”. Obviously
there are m love-hate zones in every west-east road. When passing a
love-hate zone, Panagola may get happier or less happy, depending on how
many people love him or hate him in that zone. So we can give every
love-hate zone a “welcome value” which may be negative, zero or
positive. As his secretary, you must make Panagola as happy as possible.
So you have to find out the best route ----- of which the sum of the
welcome values is maximal. You decide where to start the parade and
where to end it.

When seeing his Citizens, Panagola
always waves his hands. He may get tired and need a break. So please
never make Panagola travel in a same west-east road for more than k
minutes. If it takes p minutes to pass a love-hate zone, we say the
length of that love-hate zone is p. Of course you know every love-hate
zone’s length.

The figure below illustrates the case in sample input. In this figure, a best route is marked by thicker lines.

 
Input
There are multiple test cases. Input ends with a line containing three zeros.
Each test case consists of 2×n + 3 lines.

The first line contains three integers: n, m and k.(0<n<=100,0<m<=10000, 0<=k<=3000000)

The
next n+1 lines stands for n + 1 west-east roads in north to south
order. Each line contains m integers showing the welcome values of the
road’s m love-hate zones, in west to east order.

The last n+1
lines also stands for n + 1 west-east roads in north to south order.
Each line contains m integers showing the lengths (in minutes) of the
road's m love-hate zones, in west to east order.

 
Output
For each test case, output the sum of welcome values of the best route. The answer can be fit in a 32 bits integer.
 
Sample Input
2 3 2
7 8 1
4 5 6
1 2 3
1 1 1
1 1 1
1 1 1
0 0 0
 
Sample Output
27
 
Source
 题意: F城是由n+1条横向路和m+1条竖向路组成。你的任务是从最南边的路走到最北边的路,使得走过的路上的高兴值和最大(注意,一段路上的高兴值可能是负 数)。同一段路不能经过两次,且不能从北往南走,另外,在每条横向路上所花的时间不能超过k。求从南到北走完可以获得的最大高兴值。
题解: 学习dp 任何一个状态可以是由下一行的-k<t<k 的状态转移过来,所以是一个dp问题,现在先预处理出每一行到当前位置的前缀和用sum[i][j]保存下来,
dp[i][j]表示到第i行第j列的时候最大的高兴值,这个时候下一行的dp[i+1][j]已经处理出来了
假设当前位置是由下一行的第k个格子转移来的,当k<=j 的时候有 dp[i][j] = dp[i+1][k] + sum[i+1][j] - sum[i+1][k] ——(1式)
                       当k>  j 的时候有 dp[i][j] = dp[i+1][k] + sum[i+1][k] - sum[i+1][j] ——(2式)
所以有dp[i][j] = max(dp[i][j] , (1式) ,(2式) ) ;
考虑每次枚举k的话,复杂度是n*m*m 肯定会超时,所以像一个不用枚举k 的方法——单调队列优化dp
根据转移方程1 dp[i+1][k] - sum[i+1][k] 和k 有关,则设F(K) = dp[i+1][k] - sum[i+1][k]  这样只要在向上转移的时候,只要在转移范围之内,并且维护下一行的F(k) 是一个单调队列,及永远是最大值在最后面,
现在的问题就是要预处理出每个点的转移范围,即对每一行的第i个位置的 t 相加,从0加到t,如果大于k则从1开始逐个递减,这样从前向后扫描一边,因为t肯定是正数所以扫描一遍即可预处理所有的左边界,
再从后向前扫描一边即可预处理出所有的右边界,然后用一个优先队列储存使得f(k)在转移范围内的从小到大的k值,则最后肯定是从这个k值转移到此状态是大的高兴值
 
这里注意一个小细节,就是一共有n+1行
 
 代码:
 #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 ;
}

Parade(单调队列优化dp)的更多相关文章

  1. LA 4327 Parade(单调队列优化dp)

    题目链接: 题目大意(摘自刘汝佳<<算法竞赛入门经典--训练指南>>):F城是由n+1条横向路和m+1条竖向路组成.你的任务是从最南边的路走到最北边的路,使得走过的路上的高兴值 ...

  2. 单调队列优化DP,多重背包

    单调队列优化DP:http://www.cnblogs.com/ka200812/archive/2012/07/11/2585950.html 单调队列优化多重背包:http://blog.csdn ...

  3. 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 ...

  4. hdu3401:单调队列优化dp

    第一个单调队列优化dp 写了半天,最后初始化搞错了还一直wa.. 题目大意: 炒股,总共 t 天,每天可以买入na[i]股,卖出nb[i]股,价钱分别为pa[i]和pb[i],最大同时拥有p股 且一次 ...

  5. BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP

    BZOJ_3831_[Poi2014]Little Bird_单调队列优化DP Description 有一排n棵树,第i棵树的高度是Di. MHY要从第一棵树到第n棵树去找他的妹子玩. 如果MHY在 ...

  6. 【单调队列优化dp】 分组

    [单调队列优化dp] 分组 >>>>题目 [题目] 给定一行n个非负整数,现在你可以选择其中若干个数,但不能有连续k个数被选择.你的任务是使得选出的数字的和最大 [输入格式] ...

  7. [小明打联盟][斜率/单调队列 优化dp][背包]

    链接:https://ac.nowcoder.com/acm/problem/14553来源:牛客网 题目描述 小明很喜欢打游戏,现在已知一个新英雄即将推出,他同样拥有四个技能,其中三个小技能的释放时 ...

  8. 单调队列以及单调队列优化DP

    单调队列定义: 其实单调队列就是一种队列内的元素有单调性的队列,因为其单调性所以经常会被用来维护区间最值或者降低DP的维数已达到降维来减少空间及时间的目的. 单调队列的一般应用: 1.维护区间最值 2 ...

  9. BZOJ1791[Ioi2008]Island 岛屿 ——基环森林直径和+单调队列优化DP+树形DP

    题目描述 你将要游览一个有N个岛屿的公园.从每一个岛i出发,只建造一座桥.桥的长度以Li表示.公园内总共有N座桥.尽管每座桥由一个岛连到另一个岛,但每座桥均可以双向行走.同时,每一对这样的岛屿,都有一 ...

随机推荐

  1. 为什么epoll会那么高效

    参考(原文简直超赞):https://zhidao.baidu.com/question/687563051895364284.html下面是我结合原文写的,为了便于自己理解:关于阻塞和非阻塞的理解可 ...

  2. JaveScript流程控制(JS知识点归纳四)

    01 流程控制 顺序结构: 程序的默认执行方式 条件判断语句:也称之为分支结构,选择结构:如果程序要执行的代码出现了多种情况需要使用 循环结构:当代码需要多次重复执行多次时,使用 02 条件判断语句 ...

  3. CSS 水平居中/布局 垂直居中 (月经问题)

    水平居中 如果它是一个行内元素 对其父元素使用 text-align:center 即可实现. <p style = " text-align:center; width:300px; ...

  4. 正确使用volatile场景--状态标志

    同步机制:volatile 特点:可见性:不具备原子性 每个线程有自己单独的内存:如果线程1和线程2公用一个变量name:如果两个线程并发进行,并且需要访问变量name:如果这个变量具有了可见性,线程 ...

  5. Java基础之引用(String,char[],Integer)总结

    1.String的引用: 下列代码执行后的结果为: public class Test { public static void main(String[] args) { StringBuffer  ...

  6. iOS学习——iOS 整体框架及类继承框架图

    整理自:IOS 整体框架类图值得收藏 一 整体框架 在iOS开发过程中,对iOS的整理框架的了解和学习是必不可少的一个环节,今天我们就好好来了解一下iOS的整体框架.首先贴一个关于iOS的框架介绍:i ...

  7. PHP生成验证码

    <?php check_code(); function check_code($width = 100, $height = 50, $num = 4, $type = 'jpeg') { $ ...

  8. LeetCode题目总结(三)

    我的代码在github上,https://github.com/WINTERFELLS/LeetCode-Answers 这里只提供个人的解题思路,不一定是最好的. 41-60: 给定一个排好序的数组 ...

  9. HTML5 使用FileReader实现调用相册、拍照功能

    HTML5定义了FileReader作为文件API的重要成员用于读取文件,根据W3C的定义,FileReader接口提供了读取文件的方法和包含读取结果的事件模型. FileReader的使用方式非常简 ...

  10. C#winform程序关闭计算机的正确姿势

    /// <summary> /// 计算机电源控制类 /// </summary> public class EnvironmentCheckClass { [DllImpor ...