zoukankan      html  css  js  c++  java
  • hdu 3401 单调队列优化动态规划

    思路:

    动态方程很容易想到dp[i][j]=max(dp[i][j],dp[i-w-1][j-k]-k*ap[i],dp[i-w-1][j+k]+k*bp[i]);

    dp[i][j]表示第i天拥有j个石头的最大价值。

    其实每次求得都是最有策略,所有dp[i-w-1]表示的就是i-w-1以前的最优,故不同往前遍历。

    那么主要需要优化的是:

    对于买石头,容量为j时,维护从j-k到j的转移最大值。即从哪个容量转移过来能得到最大效益。

    对于卖石头,容量为j时,维护从j+k到j的转移最大值。即从哪个容量转移过来能得到最大效益。

    见代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define inf 10000010
    #define Maxn 2010
    #define Min(a,b) (a)>(b)?(b):(a)
    using namespace std;
    int dp[Maxn][Maxn],as[Maxn],bs[Maxn],ap[Maxn],bp[Maxn];
    struct Que{
        int val,pos;
    }que[10000];
    int main()
    {
        int n,t,p,w,i,j,k;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d%d",&n,&p,&w);
            for(i=1;i<=n;i++)
                for(j=0;j<=p;j++)
                dp[i][j]=-inf;//初始化
            for(i=1;i<=n;i++)
                scanf("%d%d%d%d",ap+i,bp+i,as+i,bs+i);
            for(i=1;i<=w+1;i++)//预处理
                for(j=0;j<=as[i];j++)
                    dp[i][j]=-j*ap[i];
            for(i=2;i<=n;i++)
            {
                for(j=0;j<=p;j++)
                dp[i][j]=max(dp[i][j],dp[i-1][j]);//预处理
                if(i<=w+1) continue;
                int head=1,rear=0;
                for(j=0;j<=p;j++)//买石头
                {
                    while(head<=rear&&(que[rear].val-(j-que[rear].pos)*ap[i])<=dp[i-w-1][j])
                        rear--;
                    que[++rear].pos=j,que[rear].val=dp[i-w-1][j];
                    if(que[head].pos<j-as[i]) head++;
                    dp[i][j]=max(dp[i][j],que[head].val+(que[head].pos-j)*ap[i]);
                }
                head=1,rear=0;
                for(j=p;j>=0;j--)//卖石头
                {
                    while(head<=rear&&(que[rear].val+(que[rear].pos-j)*bp[i])<=dp[i-w-1][j])
                        rear--;
                    que[++rear].pos=j,que[rear].val=dp[i-w-1][j];
                    if(que[head].pos>j+bs[i]) head++;
                    dp[i][j]=max(dp[i][j],que[head].val+(que[head].pos-j)*bp[i]);
                }
            }
            int Max=0;
            for(i=0;i<=p;i++)//找出最大效益
                if(dp[n][i]>Max)
                Max=dp[n][i];
            printf("%d
    ",Max);
        }
        return 0;
    }
  • 相关阅读:
    第四章 变量的三大特征,垃圾回收机制,可变类型和不可变类型的简单表述
    第三章 有关变量的理解
    第二章 编程语言的分类及优缺点的分析
    IIS拓展访问的文件格式
    JS之HTTP请求
    HTTP请求
    HtmlAgilityPack解析html
    支付宝支付功能开发
    Web.config配置ActiveReports
    数据库连接字符串
  • 原文地址:https://www.cnblogs.com/wangfang20/p/3238245.html
Copyright © 2011-2022 走看看