简单DP,题解见代码
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 #define mem0(a) memset(a,0,sizeof(a)) 5 #define MAX(a, b) (a > b ? a : b) 6 using namespace std; 7 8 struct BondsV_I 9 { 10 int Value; 11 int Interest; 12 }Bonds[11]; 13 int Amount, Year, BondsNum; 14 int dp[50005];//由于题目说利率不会超过10%,所以也就是不会超过1000*1.1^40,小于50000 15 16 int main() 17 { 18 int Case; 19 while(~scanf("%d", &Case))while(Case--) 20 { 21 mem0(Bonds); 22 scanf("%d%d", &Amount, &Year); 23 scanf("%d", &BondsNum); 24 for(int i=1;i<=BondsNum;i++) 25 { 26 scanf("%d %d", &Bonds[i].Value, &Bonds[i].Interest); 27 Bonds[i].Value/=1000;//题目说Value都是1000的倍数,所以直接/1000减小复杂度 28 } 29 int ans = Amount; 30 for(int year = 1; year <= Year; year ++)//由于存钱的利息一次性投两年和分开投结果没区别, 31 //甚至一年后可能还会有更好的方式,所以下一年可以只有上一年得到 32 { 33 mem0(dp);//dp保存的是这一年所获得的的利息 34 for(int i=1;i<=BondsNum;i++)//对于每一种方式 35 { 36 for(int j=Bonds[i].Value;j<=ans/1000;j++)//由于可以选择任意多个,所以是完全背包 37 { //Value/1000,所以相应的钱/1000 38 dp[j] = MAX(dp[j-Bonds[i].Value] + Bonds[i].Interest, dp[j]); 39 } 40 } 41 ans += dp[ans/1000];//更新这一年获得的数目 42 } 43 printf("%d ", ans); 44 } 45 return 0; 46 }