hdu4374One hundred layer (DP+单调队列)

时间:2021-06-14 23:55:56

http://acm.hdu.edu.cn/showproblem.php?pid=4374

去年多校的题 今年才做 不知道这一年都干嘛去了。。

DP的思路很好想 dp[i][j] = max(dp[i-1][g]+sum[i][j]-sum[i][g-1],dp[i][j]) abs(g-j)<=t  不过复杂度是相当高的 所以呢 就出现了个单调队列 把它优化下

所谓的单调队列其实也就是一队列 始终保持着队头是最大的 若满足不了距离的条件 队头+1 队尾始终保持更新 让满足的了距离而且比队里的更大的元素进来

。。因为一初始化错了  WA了十多次啊 注意:有负数

 #include <iostream>
#include<cstdio>
#include<cstring>
#include<stdlib.h>
#include<algorithm>
using namespace std;
#define N 105
#define M 10005
#define LL __int64
int a[N][M],que[M];
int dp[N][M];
int s1[N][M],s2[N][M];
int main()
{
int i,j,n,m,x,t,str,end;
while(cin>>n>>m>>x>>t)
{
memset(dp,,sizeof(dp));
memset(s1,,sizeof(s1));
memset(s2,,sizeof(s2));
for(i = ; i <= n; i++)
for(j = ; j <= m ; j++)
{
scanf("%d",&a[i][j]);
s1[i][j] = s1[i][j-]+a[i][j];
}
for(i = ; i <= n ;i++)
for(j = m ; j >= ; j--)
s2[i][j] = s2[i][j+]+a[i][j];
for(i = x ; i>=&&i>=x-t ; i--)
dp[][i] = s1[][x]-s1[][i-];
for(i = x ; i <= m&&i<=x+t ; i++)
dp[][i] = s2[][x]-s2[][i+];
for(i = ; i <= n ; i++)
{
str = ;end=;
for(j = ;j <= m ; j++)
{
while(str<end&&dp[i-][j]-s1[i][j-]>dp[i-][que[end-]]-s1[i][que[end-]-])
end--;
que[end++] = j;
dp[i][j] = max(dp[i][j],dp[i-][que[str]]-s1[i][que[str]-]+s1[i][j]);
if(j-que[str]>=t)
str++;
}
str = ;end=;
for(j = m ; j >= ; j--)
{
while(str<end&&dp[i-][j]-s2[i][j+]>dp[i-][que[end-]]-s2[i][que[end-]+])
end--;
que[end++] = j;
dp[i][j] = max(dp[i][j],dp[i-][que[str]]-s2[i][que[str]+]+s2[i][j]);
if(que[str]-j>=t)
str++;
}
}
int maxz=dp[n][];
for(i = ; i <= m ; i++)
maxz = max(maxz,dp[n][i]);
cout<<maxz<<endl;
}
return ;
}