zoukankan      html  css  js  c++  java
  • 【刷题】【deque优化dp】股票交易

    先写普通dp,得分70,

    写的时候要注意dp的顺序,

    如果原来有值,不可以直接覆盖,要判断,

    如果上一次可行,这一次可以不改变,要把状态转移过来

    memset(128)就是刷新成-inf

    无优化dp:

    //先写一遍普通dp练手 
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    int n,mxp,w;
    const int N=2003;
    int in[N],out[N];
    ll a[N],b[N],f[N][N]; 
    
    inline int read()
    {
        int x=0;char c=getchar();
        while(c<'0' || c>'9') c=getchar();
        while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar();
        return x;
    }
    
    int main()
    {
        n=read(),mxp=read(),w=read();
        memset(f,128,sizeof(f));
        for(int i=1;i<=n;i++)
        {
            a[i]=read(),b[i]=read(),in[i]=read(),out[i]=read();
            for(int j=0;j<=in[i] && j<=mxp ;j++) f[i][j]=-1*a[i]*j;
            for(int j=0;j<=mxp;j++) f[i][j]=max(f[i][j],f[i-1][j]);
    
            if(i>w+1)
            for(int j=0;j<=mxp;j++)
            {
                for(int k=1;k<=in[i] && j>=k ;k++)
                    f[i][j]=max(f[i][j],f[i-w-1][j-k] -a[i]*k);
                for(int k=1;k<=out[i] && j+k<=mxp ;k++)
                    f[i][j]=max(f[i][j],f[i-w-1][j+k] +b[i]*k); 
            }
        }
        
        printf("%d
    ",f[n][0]);
        return 0;
    }

     考虑优化,

    ​ 买入时:

    ​ f[i][j]= f[i-w-1][k] -a[i] * (j-k)     k<=j && k>=j-in[i] 

    ​    = f[i-w-1][k] +a[i]*k   - a[i] * j         

    ​我们发现,对于每一个i,都枚举了j*k,

    但是 j和k 其实是可以分离的,所以其实可以降成 j+k,然后用单调队列优化,

    先处理k,再给j赋值

    卖出时

    f[i][j]= f[i-w-1][k] +b[i]*(k-j)       k<=mxp && k<=j+out[i] && k>j

       = f[i-w-1][k] +b[i]*k  -b[i]*j

    所以买入的时候,j,k从小到大,把最可能出队的小的k,放在队头,

    卖出的时候,j,k从大到小。

    //先写一遍普通dp练手 
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define ll long long
    using namespace std;
    int n,mxp,w;
    const int N=2003;
    int in[N],out[N];
    ll a[N],b[N],f[N][N]; 
    
    inline int read()
    {
        int x=0;char c=getchar();
        while(c<'0' || c>'9') c=getchar();
        while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar();
        return x;
    }
    
    struct node
    {int v,pos;};
    deque <node> q;
    int main()
    {
        n=read(),mxp=read(),w=read();
        
        memset(f,128,sizeof(f));
        int inf=f[0][0];
        for(int i=1;i<=n;i++)
        {
            a[i]=read(),b[i]=read(),in[i]=read(),out[i]=read();
            for(int j=0;j<=in[i] && j<=mxp ;j++) f[i][j]=-1*a[i]*j;
            for(int j=0;j<=mxp;j++) f[i][j]=max(f[i][j],f[i-1][j]);
    
            if(i>w+1)
            {
                q.clear() ;
                int pre=i-w-1;
                for(int j=0;j<=mxp;j++)//等下想怎么去掉无用状态 
                {
                    if(!q.empty() && q.front() .pos < j-in[i])
                        q.pop_front() ;
                    int val=f[pre][j] +a[i]*j;
                    while(!q.empty() && q.back() .v <=val)
                        q.pop_back() ;
                    q.push_back((node){val,j});
                    
                    f[i][j]=max(f[i][j],q.front() .v-a[i]*j); 
                }
                
                q.clear() ;
                for(int j=mxp;~j;j--)
                {
                    if(!q.empty() && q.front() .pos > j+out[i])
                        q.pop_front() ;
                    int val=f[pre][j] +b[i]*j;
                    while(!q.empty() && q.back() .v <=val)
                        q.pop_back() ;
                    q.push_back((node){val,j});
                    
                    f[i][j]=max(f[i][j],q.front() .v-b[i]*j); 
                }
            }
        }
        
        printf("%d
    ",f[n][0]);
        return 0;
    }
  • 相关阅读:
    使用循环计算斐波那契数列
    java 面向过程实现万年历
    学习js回调函数
    序列化和反序列化
    SQL语句增加字段、修改字段、修改类型、修改默认值
    使用SQL语句查询日期(当月天数,当月第一天,当月最后一天,本年最后一天,当月第一个星期) 日期转字符串
    RGB颜色表
    String 与StringBuilder有什么区别
    C# byte数组与Image的相互转换
    CentOS 7 MySQL、Tomcat、Zookeeper设置开机自启
  • 原文地址:https://www.cnblogs.com/xwww666666/p/11694307.html
Copyright © 2011-2022 走看看