您的位置:首页 > 其它

hdu 4374 One hundred layer (DP+单调队列)@

2017-04-15 10:54 429 查看
Now there is a game called the new man down 100th floor. The rules of this game is: 

   1.  At first you are at the 1st floor. And the floor moves up. Of course you can choose which part you will stay in the first time. 

   2.  Every floor is divided into M parts. You can only walk in a direction (left or right). And you can jump to the next floor in any part, however if you are now in part “y”, you can only jump to part “y” in the next floor! (1<=y<=M) 

   3.  There are jags on the ceils, so you can only move at most T parts each floor. 

   4.  Each part has a score. And the score is the sum of the parts’ score sum you passed by. 

Now we want to know after you get the 100th floor, what’s the highest score you can get.

InputThe first line of each case has four integer N, M, X, T(1<=N<=100, 1<=M<=10000, 1<=X, T<=M). N indicates the number of layers; M indicates the number of parts. At first you are in the X-th part. You can move at most T parts in
every floor in only one direction. 

Followed N lines, each line has M integers indicating the score. (-500<=score<=500)
OutputOutput the highest score you can get.
Sample Input
3 3 2 1
7 8 1
4 5 6
1 2 3


Sample Output
29


题意:给定n*m的矩阵,每个格点有一个权值,给定开始的位置,每层可以向左或向右移动不超过t的单位长度,但只能走一个方向,走到一个格点就可以得到当前的权值;

向下移动只能到垂直向下的格点,求最后能得到的最大权值

解:这个题状态转移,从左边来的 dp[i][j] =  dp[i-1][k] + dis(k,j) 先预处理出一个sum数组存每一行前i个元素的和,dp[i][j] = dp[i-1][k] + sum[i][j]-sum[i][k-1];用单调队列了,在队列首部存放dp[i-1][k]-sum[i][k-1]最大值的下标。如果当前点的权值比队列尾部的权值大就更新;

因为权值可能有负数,所以DP方程初始化为极小值

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
const int N = 1e4+10;
int dp[110]
, sum[110]
, p[110]
, q
;

int main()
{
int n, m, x, t1;
while(scanf("%d %d %d %d", &n, &m, &x, &t1)!=EOF)
{
memset(sum,0,sizeof(sum));
memset(dp,128,sizeof(dp));

for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
scanf("%d", &p[i][j]);
sum[i][j]=sum[i][j-1]+p[i][j];
}
}
for(int i=x; i>=x-t1&&i>=1; i--) dp[1][i]=sum[1][x]-sum[1][i-1];
for(int i=x+1; i<=x+t1&&i<=m; i++) dp[1][i]=sum[1][i]-sum[1][x-1];
for(int i=2;i<=n;i++)
{
int s=0, t=0;
for(int j=1;j<=m;j++)
{
while(s<t&&dp[i-1][j]-sum[i][j-1]>dp[i-1][q[t-1]]-sum[i][q[t-1]-1]) t--;
q[t++]=j;
while(s<t&&j-q[s]>t1) s++;
dp[i][j]=dp[i-1][q[s]]+sum[i][j]-sum[i][q[s]-1];
}
s=0, t=0;
for(int j=m;j>=1;j--)
{
while(s<t&&dp[i-1][j]+sum[i][j]>dp[i-1][q[t-1]]+sum[i][q[t-1]]) t--;
q[t++]=j;
while(s<t&&q[s]-j>t1) s++;
dp[i][j]=max(dp[i][j],dp[i-1][q[s]]+sum[i][q[s]]-sum[i][j-1]);
}
}

int ans=dp
[1];
for(int i=2; i<=m; i++) ans=max(ans,dp
[i]);
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: