• SCOI2010 股票交易


    题目链接:戳我

    看到这个题目,我们有一个朴素的DP想法(但是为什么我会先想到网络流啊喂,果然是菜鸡

    (dp[i][j][0/1/2])表示第i天不进行交易/买入/卖出,现在手上有j张票,前i天能够获得的最大收益。转移什么的随便弄弄就行了吧。

    然后发现自己智障了,0/1/2根本不用划分好吗.......于是就变成了这个样子......(dp[i][j])表示现在手上有j张票,前i天能够获得的最大收益。

    (dp[i][j]=max(dp[i][j],dp[i-1][j]))
    (dp[i][j]=max(dp[i][j],dp[i-w-1][k]-ap[i]*(j-k)))
    (dp[i][j]=max(dp[i][j],dp[i-w-1][k]+bp[i]*(k-j)))

    于是50分到手。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #define MAXN 2010
    using namespace std;
    int n,m,w;
    int ap[MAXN],bp[MAXN],as[MAXN],bs[MAXN];
    long long dp[MAXN][MAXN];
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d%d%d",&n,&m,&w);
        for(int i=1;i<=n;i++)
            scanf("%d%d%d%d",&ap[i],&bp[i],&as[i],&bs[i]);
        for(int i=0;i<=n;i++)
            for(int j=0;j<=m;j++)
                dp[i][j]=-0x3f3f3f3f3f3f3f3f;
        dp[0][0]=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<=m;j++)
            {
                dp[i][j]=max(dp[i][j],dp[i-1][j]);
                for(int k=max(0,j-as[i]);k<=j-1;k++)
                {
                    int cur=max(0,i-w-1);
                    dp[i][j]=max(dp[i][j],dp[cur][k]-1ll*ap[i]*(j-k));
                }
                for(int k=j+1;k<=m&&k<=j+bs[i];k++)
                {
                    int cur=max(0,i-w-1);
                    dp[i][j]=max(dp[i][j],dp[cur][k]+1ll*bp[i]*(k-j));
                }
            }
        }
        long long ans=0;
        for(int i=0;i<=m;i++) ans=max(ans,dp[n][i]);
        printf("%lld
    ",ans);
        return 0;
    }
    

    之后我们考虑一下怎么把这个K给去掉。
    把转移方程化一下:
    (dp[i][j]=max(dp[i-1][j]))
    (dp[i][j]=max(dp[i-w-1][k]+k*ap[i])-ap[i]*j (j-as[i]le k le j-1))
    (dp[i][j]=max(dp[i-w-1][k]+k*bp[i])+bp[i]*j (j+1le kle j+bs[i]))

    我们发现那个取max的部分是可以用单调队列优化的.......
    于是就100pts了

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #define MAXN 2010
    using namespace std;
    int n,m,w;
    int ap[MAXN],bp[MAXN],as[MAXN],bs[MAXN],q[MAXN];
    long long dp[MAXN][MAXN];
    int main()
    {
    	#ifndef ONLINE_JUDGE
    	freopen("ce.in","r",stdin);
    	#endif
    	scanf("%d%d%d",&n,&m,&w);
    	for(int i=1;i<=n;i++)
    		scanf("%d%d%d%d",&ap[i],&bp[i],&as[i],&bs[i]);
    	for(int i=0;i<=n;i++)
    		for(int j=0;j<=m;j++)
    			dp[i][j]=-0x3f3f3f3f3f3f3f3f;
    	for(int i=1;i<=n;i++) dp[i][0]=0;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=0;j<=as[i];j++) dp[i][j]=-ap[i]*j;
    		for(int j=0;j<=m;j++) dp[i][j]=max(dp[i][j],dp[i-1][j]);
    		if(i-w-1>=0)
    		{
    			int head=1,tail=0;
    			for(int j=0;j<=m;j++)
    			{
    				while(head<=tail&&q[head]<j-as[i]) head++;
    				while(head<=tail&&dp[i-w-1][j]+ap[i]*j>=dp[i-w-1][q[tail]]+ap[i]*q[tail]) tail--;
    				q[++tail]=j;
    				dp[i][j]=max(dp[i][j],dp[i-w-1][q[head]]-ap[i]*(j-q[head]));
    			}
    			head=1,tail=0;
    			for(int j=m;j>=0;j--)
    			{
    				while(head<=tail&&q[head]>j+bs[i]) head++;
    				while(head<=tail&&dp[i-w-1][j]+j*bp[i]>=dp[i-w-1][q[tail]]+q[tail]*bp[i]) tail--;
    				q[++tail]=j;
    				dp[i][j]=max(dp[i][j],dp[i-w-1][q[head]]+bp[i]*(q[head]-j));
    			}
    		}
    	}
    	long long ans=0;
    	for(int i=0;i<=m;i++) ans=max(ans,dp[n][i]);
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    (2)Bitmap类相关——extractAlpha
    (3)android 图片编辑要注意的点
    HDU 1588 Gauss Fibonacci 矩阵
    HDU 1575 Tr A 矩阵快速幂
    CF R274 Div2 E Riding in a Lift DP
    ZOJ 3829 Known Notation 贪心
    ZOJ 3820 Building Fire Stations 贪心+树的直径
    ZOJ 3822 Domination DP
    ZOJ 3826 Hierarchical Notation Hash+模拟
    TC SRM 636 Div2 C ChocolateDividingHard 二分
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10888289.html
Copyright © 2020-2023  润新知