题目传送门https://www.luogu.com.cn/problem/P1853
思路分析:
1.这道题并没有说一种券只能买一次,所以是一道很浅显的完全背包。
2.因为他每次都可以再买,所以要从1到n进行一次额外的遍历
3.这道题你不进行同比例的缩放就过不了,利用x年级学的比例,就能轻松解决此题。
小结一下:我们要将每一年得到的钱再加上本金,投入下一年的投资,这样才能实现最值。
注释代码:
#include<bits/stdc++.h>
using namespace std;
int w[100000];
int v[100000];
int dp[100000];
int s,n,d;
int main(){
scanf("%d%d%d",&s,&n,&d);
for(int i=1;i<=d;i++){
scanf("%d%d",&w[i],&v[i]);
}
for(int i=1;i<=n;i++){//n年遍历
int m=s/1000;//由于题目说了是1000的倍数,可以除以1000来减少空间
//完全背包模板
for(int j=1;j<=d;++j){
for(int k=w[j]/1000;k<=m;k++){
if(k>=w[j]/1000) dp[k]=max(dp[k],dp[k-w[j]/1000]+v[j]);
}
}
s+=dp[m];//答案累加
memset(dp,0,sizeof(dp));//初始状态清零
}
printf("%d",s);
}
纯净代码:
#include<bits/stdc++.h>
using namespace std;
int w[100000];
int v[100000];
int dp[100000];
int s,n,d;
int main(){
scanf("%d%d%d",&s,&n,&d);
for(int i=1;i<=d;i++){
scanf("%d%d",&w[i],&v[i]);
}
for(int i=1;i<=n;i++){
int m=s/1000;
for(int j=1;j<=d;++j){
for(int k=w[j]/1000;k<=m;k++){
if(k>=w[j]/1000) dp[k]=max(dp[k],dp[k-w[j]/1000]+v[j]);
}
}
s+=dp[m];
memset(dp,0,sizeof(dp));
}
printf("%d",s);
}