题意:
有 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; }