hdu4374 One hundred layer(单调队列维护dp)
2017-10-25 19:26
489 查看
题面
题意
给出宽n,长m的矩阵,你一开始在第一行第k个,在每行你最多向左或向右移动t步(在底层和顶层皆可移动),移动后进入下一层,问到达底层后的最大分数是多少.方法
用dp思想可知,只需要知道到达每一点的最大得分是多少,若穷举每行的起点和终点进行状态转移,复杂度为O(n*m^2)必然TLE.其实在第i行若终点为j,则起点必然在max(1,j-t)与min(m,j+t)之间,对于此类求区间最大值的题目当用单调队列来维护,则复杂度为O(n*m).
也可以这么想:
不难得到状态转移方程:
在第i行中,k为起点,j为终点,qz表示前缀和
j>=k时
dp[i][j]=dp[i-1][k]+qz[i][j]-qz[i][k-1] ->
dp[i][j]-qz[i][j]=dp[i-1][k]-qz[i][k-1]
j<=k时
dp[i][j]=dp[i-1][k]+qz[i][k]-qz[i][j-1]->
dp[i][j]+qz[i][j-1]=dp[i-1][k]+qz[i][k]
因而只需用单调队列求出等号右边的最小值
代码
#include<bits/stdc++.h> #define ll long long #define M 110 #define N 10100 #define MN -100000000 using namespace std; ll m,n,k,l,num[M][N],qz[M][N],last[N],now,dp[M][N],ans; struct Dq { ll nu ,id ,head,tail,len; void init() { head=1; tail=0; } void push(ll u,ll v) { if(head<=tail&&v-id[head]>=len) head++; while(head<=tail&&u>=nu[tail]) tail--; tail++; nu[tail]=u; id[tail]=v; } ll front() { return nu[head]; } ll front2() { return id[head]; } void pop() { head++; } bool empty() { if(head>tail) return 1; return 0; } void getlen(ll u) { len=u; } void print() { ll i; for(i=head;i<=tail;i++) { cout<<nu[i]<<" "; } cout<<endl; } void print2() { ll i; cout<<head<<" "<<tail<<endl; for(i=head;i<=tail;i++) { cout<<nu[i]<<" "; } cout<<endl; } }; Dq dq; int main() { ll i,j; while(~scanf("%lld%lld%lld%lld",&m,&n,&k,&l)) { dq.getlen(l+1); for(i=1;i<=m;i++) { for(j=1;j<=n;j++) { scanf("%lld",&num[i][j]); } } for(i=1;i<=m;i++) { qz[i][1]=num[i][1]; for(j=2;j<=n;j++) { qz[i][j]=qz[i][j-1]+num[i][j]; } } for(i=1;i<=n;i++) dp[1][i]=MN; dp[1][k]=num[1][k]; for(i=k+1;i<=min(k+l,n);i++) dp[1][i]=dp[1][i-1]+num[1][i]; for(i=k-1;i>=max((ll)1,k-l);i--) dp[1][i]=dp[1][i+1]+num[1][i]; for(i=2;i<=m;i++) { //left dq.init(); for(j=1;j<=n;j++) { dq.push(dp[i-1][j]+qz[i][j],j); if(j>l) dp[i][j-l]=dq.front()-qz[i][j-l-1]; } for(j=1;j<=min(l,n);j++) { while(!dq.empty()&&dq.front2()<n-l+j) dq.pop(); dp[i][n-l+j]=dq.front()-qz[i][n-l+j-1]; } //right dq.init(); for(j=n;j>=1;j--) { dq.push(dp[i-1][j]-qz[i][j-1],n-j+1); if(j<=n-l) dp[i][j+l]=max(dp[i][j+l],dq.front()+qz[i][j+l]); } for(j=1;j<=l;j++) { while(!dq.empty()&&n-dq.front2()+1>l-j+1) dq.pop(); dp[i][l-j+1]=max(dp[i][l-j+1],dq.front()+qz[i][l-j+1]); } } ans=MN; for(i=1;i<=n;i++) { ans=max(ans,dp[m][i]); } printf("%lld\n",ans); } } /* right : dp[i][j]=dp[i-1][k]+qz[i][j]-qz[i][k-1] dp[i][j]-qz[i][j]=dp[i-1][k]-qz[i][k-1] left : dp[i][j]=dp[i-1][k]+qz[i][k]-qz[i][j-1] dp[i][j]+qz[i][j-1]=dp[i-1][k]+qz[i][k] */
相关文章推荐
- HDU4374:One hundred layer(dp+单调队列优化)
- 【HDU4374】One hundred layer-单调队列优化DP
- HDU 4374 One hundred layer(单调队列优化dp)
- hdu 4374 One hundred layer 单调队列优化dp
- HDU 4374 One hundred layer [单调队列优化DP]
- HDU 4374 One hundred layer(DP+单调队列优化)
- [DP] hdu 4374 One hundred layer #单调队列优化
- hdu 4374 One hundred layer (DP+单调队列)@
- hdu 4374 One hundred layer【单调队列DP】
- hdu 4374 One hundred layer(单调队列优化dp)
- HDU 4374 One hundred layer DP的单调队列优化
- HDU 4374 One hundred layer(单调队列+DP)
- hdu 4374 One hundred layer 单调队列优化dp
- MUTC8 E- One hundred layer 单调队列dp
- MUTC8 E- One hundred layer 单调队列dp
- 单调队列HDU 4374 One hundred layer
- 【单调队列】 HDOJ One hundred layer
- hdu4374(单调队列优化dp)
- hdu4374 One hundred layer
- HDU 5945 维护一个单调队列 dp