HDU2490 Parade 单调队列优化DP

来源:互联网 发布:网络信息安全重大事件 编辑:程序博客网 时间:2024/05/16 11:43

Parade

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


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 27 8 14 5 61 2 31 1 11 1 11 1 10 0 0
 

Sample Output
27

题解:很容易想到dp方程,但是需要使用单调队列进行优化。

令dp[i][j]表示从最下面走到第i行的第j的交叉点所获得的最大happy值

那么转移方程就是:

dp[i][j] = max(dp[i+1][t] + | sum_val[i][j] - sum_val[i][t] | )

如果我们规定每行的扫描方向的话,可以去掉绝对值符号,但是我们需要扫描两遍,因此,我们从左扫一遍,从右扫一遍,并同时用单调队列进行优化。

我们从左往右扫到第j个的时候,把j加入到单调队列中去(其中单调队列的关键值为dp[i+1][t] - sum_val[i][t]),并删掉一些元素,继续维持单调队列的性质。

要取出的时候,我们从左边拿出一个元素t,判断与t与j的交叉点之间的距离是否>k,如果大于k则舍弃这个元素,继续从队首来取。

从右往左扫描的方法类似。这里就不赘述了。

代码:

#include <bits/stdc++.h>using namespace std;const int INF = 1e9;int cost[107][10007];int val[107][10007];int dp[107][10007];int n,m,k;inline int f1(int i,int j){return dp[i+1][j] - val[i][j];}inline int f2(int i,int j){return dp[i+1][j] + val[i][j];}int main(){while(cin>>n>>m>>k && n+m+k){for(int i = 1;i <= n+1;i++) for(int j = 0;j <= m;j++) dp[i][j] = -INF;for(int i = 0;i <= m;i++)dp[n+2][i] = 0;for(int i = 1;i <= n+1;i++){val[i][0] = 0;for(int j = 1;j <= m;j++){int tmp;scanf("%d",&tmp);val[i][j] = val[i][j-1] + tmp;}}for(int i = 1;i <= n+1;i++){cost[i][0] = 0;for(int j = 1;j <= m;j++){int tmp;scanf("%d",&tmp);cost[i][j] = cost[i][j-1] + tmp;}}//from left to rightfor(int i = n+1;i >= 1;i--){deque<int> deq;for(int j = 0;j <= m;j++){//insert while(!deq.empty() && f1(i,j) >= f1(i,deq.back())) deq.pop_back();deq.push_back(j);if(!deq.empty()){int index = deq.front();while(!deq.empty() && cost[i][j] - cost[i][index] > k){deq.pop_front();index = deq.front();}dp[i][j] = max(dp[i][j],f1(i,index) + val[i][j]);}}deq.clear();for(int j = m;j >= 0;j--){//insert while(!deq.empty() && f2(i,j) >= f2(i,deq.back())) deq.pop_back();deq.push_back(j);if(!deq.empty()){int index = deq.front();while(!deq.empty() && cost[i][index] - cost[i][j] > k){deq.pop_front();index = deq.front();}dp[i][j] = max(dp[i][j],f2(i,index) - val[i][j]);}}}int ans = -INF;for(int i = 0;i <= m;i++){ans = max(ans,dp[1][i]);}printf("%d\n",ans);}return 0;}/*2 3 27 8 14 5 61 2 31 1 11 1 11 1 10 0 0*/


原创粉丝点击