Comet OJ - Contest #11 B- usiness

原题链接

题意:

有 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;
}

 

posted @ 2019-09-24 20:50  Tianwell  阅读(166)  评论(0编辑  收藏  举报