• Comet OJ


    原题链接

    题意:

    有 n 天, m 种投资方案,以及余额小于等于 k 时的补贴 f[x] 。

    每一天可以选择投资方案进行无限次数投资(但要保证余额大于等于0),在n天结束之后投资的回报才会返回。

    求最大的投资回报为多少。

    思路:

    这种投资花钱,然后最后收获可以转化为完全背包问题。同时由于每一天的余额状态多样,所以在每一天开始也要对状态进行转移。

    设dp[i][j]为 第i天,余额为j。那么每天开始状态转移为 : dp[ i ][ j + f [ j ] ] = max ( dp[ i ][ j + f [ j ] ],dp [ i-1 ][ j ] ); // f[ j ] 为补贴函数

    然后对当天进行完全背包的转移

    code: (其他看代码注释)

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int inf = 0x3f3f3f3f; 
    int f[2050];//(0<=k<=1000),(k+f[k]<=2000)
    int v[110],w[110];//(1<=m<=100)
    int dp[105][3005];//max(i+f[i])
    int main(){
        int n,m,k;
        cin>>n>>m>>k;
        //某天手上剩余钱最大值 
        int mmax = 0; 
        for(int i=0;i<=k;i++){
            scanf("%d",&f[i]);
            mmax = max(mmax,f[i]+i);
        }
        for(int i=1;i<=m;i++){
            scanf("%d%d",&v[i],&w[i]);
        }
        memset(dp,-inf,sizeof(dp));
        dp[1][0]=0;
        for(int l=2;l<=n;l++){
            for(int j=0;j<=k;j++)
                dp[l][j+f[j]]=max(dp[l][j+f[j]],dp[l-1][j]);
            for(int i=1;i<=m;i++){
                for(int j=mmax-v[i];j>=0;j--){
                    dp[l][j]=max(dp[l][j],dp[l][j+v[i]]+w[i]);
                }
            }
        }
        //最后一天状态更新 
        int ans=0;
        for(int i=0;i<=mmax;i++){
            ans=max(ans,dp[n][i]+i+f[i]);
        }
        cout<<ans<<endl;
    }
  • 相关阅读:
    生病了,难受啊
    2005年1月31号随笔一篇
    [转]永远的Beyond
    关于IE问题,请教和求救
    中国财富排行榜
    这两天简直倒霉透顶了
    Asp.net(C#)给图片加上水印效果
    我不爱的那个女人
    555,我的hotmail从2G变回2M的了
    怀念永远的战神
  • 原文地址:https://www.cnblogs.com/Tianwell/p/11580934.html
Copyright © 2020-2023  润新知