【動態規劃19】洛谷p3800 Power收集(dp+單調隊列)

題目描述

據說在紅霧異變時,博麗靈夢單身前往紅魔館,用十分強硬的手段將事件解決了。

然而當時靈夢在Power達到MAX之前,不具有“上線收點”的能力,所以她想要知道她能收集多少P點,然而這個問題她答不上來,於是她找到了學OI的你。
可以把遊戲界面理解成一個N行M列的棋盤,有K個格子上有P點,其價值爲val(i,j)

初始靈夢可以選擇在第一行的任意一個格子出發,每秒她必須下移一格。

靈夢具有一個左右移動的速度T,可以使她每秒向左或右移動至多T格,也可以不移動,並且不能折返。移動可視爲瞬間完成,不經過路途上的點,只能獲得目標格子的P點。

求最終她能獲得的POWER值最大是多少?

(p點不是有上限的麼..)

輸入輸出格式

輸入格式:

第一行四個數字,N,M,K,T

接下來K行每行3個數字x,y,v,代表第x行第y列有一個val爲v的P點,數據保證一個格子上最多隻有1個P點。

輸出格式:

一個數字

f[i][j]表示到達f[i][j]收集的最大p點
f[i][j]=max(f[i1][k])+a[i][j](|kj|<=T)
維護區間最大值單調隊列

http://blog.csdn.net/flanoc/article/details/72904458
超偷懶的單調隊列總結

#include<bits/stdc++.h>
#define fer(i,j,n) for(int i=j;i<=n;i++)
#define far(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
const int maxn=4010;
const int INF=1e9+7;
using namespace std;
/*----------------------------------------------------------------------------*/
inline ll read()
{
    char ls;ll x=0,sng=1;
    for(;ls<'0'||ls>'9';ls=getchar())if(ls=='-')sng=-1;
    for(;ls>='0'&&ls<='9';ls=getchar())x=x*10+ls-'0';
    return x*sng;
}
/*----------------------------------------------------------------------------*/
int f[maxn][maxn],a[maxn][maxn];
int n,m,K,T;
int q[maxn],h,t,maxx;
int main()
{
    scanf("%d%d%d%d",&n,&m,&K,&T);
    fer(i,1,K)
    {
        int x=read(),y=read();
        a[x][y]=read(); 
    }
    fer(i,1,m)f[1][i]=a[1][i];
    fer(i,2,n)
    {
        h=1;t=0;
        fer(j,1,min(m,T+1))
        {
            while(h<=t&&f[i-1][j]>=f[i-1][q[t]])t--;
            q[++t]=j;
        }
        fer(j,1,m)
        {
            if(j+T<=m)
            {
                while(h<=t&&f[i-1][j+T]>=f[i-1][q[t]])t--;
                q[++t]=j+T;
            }
            if(q[h]<j-T)h++;
            f[i][j]=f[i-1][q[h]]+a[i][j];
        }
    }
    fer(i,1,m)maxx=max(maxx,f[n][i]);
    cout<<maxx;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章