hdu 4374 单调队列优化动态规划

思路:我只想说,while(head<=rear&&que[rear].val+sum[j]-sum[que[rear].pos-1]<=dp[i-1][j]+num[i-1][j])表达式中,我把最后的num[i-1][j]丢了,检查了一整天啊!一整天!我那丢失的时间!

寻找从上一层到该层中最优的转换点,如果该转化点到该点超过t就出队。

 

#include<iostream>

#include<cstring>

#include<cstdio>

#include<algorithm>

#include<cmath>

#define Maxn 110

#define Maxm 10010

#define inf 1000000000

using namespace std;

int dp[Maxn][Maxm],sum[Maxm],num[Maxn][Maxm];

int que[Maxm*5];

void init()

{

    memset(sum,0,sizeof(sum));

    memset(num,0,sizeof(num));

}

inline int ReadInt()

{

    int flag = 1;

    char ch;

    int a = 0;

    while((ch = getchar()) == ' ' || ch == '\n');

    if(ch == '-') flag = -1;

    else

    a += ch - '0';

    while((ch = getchar()) != ' ' && ch != '\n')

    {

        a *= 10;

        a += ch - '0';

    }

    return flag * a;

}

int main()

{

    int n,m,x,t,i,j,head,rear;

    while(scanf("%d%d%d%d",&n,&m,&x,&t)!=EOF){

        init();

        for(i=1;i<=n;i++){

            for(j=1;j<=m;j++){

                num[i][j]=ReadInt();

                dp[i][j]=-inf;

            }

        }

        memset(dp[0],-50,sizeof(dp));

        dp[0][x]=0;

        for(i=1;i<=n;i++){

            memset(sum,0,sizeof(sum));

            head=1,rear=0;

            for(j=1;j<=m;j++){

                sum[j]=sum[j-1]+num[i][j];

                while(head<=rear&&dp[i-1][que[rear]]+sum[j]-sum[que[rear]-1]<=dp[i-1][j]+num[i][j])

                    rear--;

                que[++rear]=j;

                while(j-que[head]>t&&head<=rear)

                    head++;

                if(head<=rear)

                dp[i][j]=dp[i-1][que[head]]+sum[j]-sum[que[head]-1];

            }

            head=1,rear=0;

            memset(sum,0,sizeof(sum));

            for(j=m;j>=1;j--){

                sum[j]=sum[j+1]+num[i][j];

                while(head<=rear&&dp[i-1][que[rear]]+sum[j]-sum[que[rear]+1]<=dp[i-1][j]+num[i][j])

                    rear--;

                que[++rear]=j;

                while(que[head]-j>t&&head<=rear)

                    head++;

                if(head<=rear)

                dp[i][j]=max(dp[i][j],dp[i-1][que[head]]+sum[j]-sum[que[head]+1]);

            }

        }

        int ans=-inf;

        for(i=1;i<=m;i++)

            ans=max(ans,dp[n][i]);

        printf("%d\n",ans);

    }

    return 0;

}

 

你可能感兴趣的:(动态规划)