dp测试T4 收益

题目背景

收益(Profit.cpp/c/pas)简单来说,就是你有一笔钱,你要将这笔钱去投资债券,现在有d种债券,每种债券都有一个价值和年收益,债券的价值是1000的倍数,问你如何投资在n年后的获得最大收益。

题目描述

输入格式

第一个为一个整数M,表示有M组数据。 每组数据第一行有两个整数,表示初始资金(不超过50000)和年数n。 每组数据第二行为一个整数d(1 ≤ d≤10),表示债券种类。 随后d行每行有两个整数,表示该债券的价值和年收益。年收益不会超过债券价值的10%。 所有数据不超过整型取值范围。

输出格式

每组数据,输出n年后获得的最大收益。

输入输出样例

输入 #1
1
10000 4
2
4000 400
3000 250
输出 #1
14050

思路:其实这个题一点也不难,就是一个背包。难就难在读题上。首先我们看样例,说实话一开始我没看懂样例什么意思,我想了好久也没明白他是怎么拿的能得到这么多钱。后来我想象那个人是我,那我肯定要把一年的利益拿出来花掉(其实我根本没想到,我想可能是这样,就把样例带进去试了试,还真是),所以我就明白样例是怎么回事了。其实他是每年获得的利益都会拿出来,然后再去投资,这样当然赚的钱更多,所以直接开始背包就行了。完全背包板子题,所以我觉得这个题主要还是考验选手的读题能力(也有可能是我语文太菜了)。把样例带进去看一下,一开始你有一万块钱去买债券,然后发现正好能买两个3000的和一个4000的(欣喜若狂ing),这样一年就赚了900块。然后拿回来,加到你手里,这样你手里现在就有10900块钱。然后你发现,只有11000你才能买两个4000的和一个3000的,才能赚到1050块(不能借100块吗?借上100块你就能多赚1050-900=150哎,我可真是经商小天才),又过了一年,也就是两年之后,你终于赚了1800块钱,可以买两个4000的和一个3000的了(哦太棒了)。这样过去一年你就会赚1050块,现在你的手里有12850块,然后你惊喜地发现,我现在可以买三个4000的了(再次欣喜若狂),这样一年就能赚1200了耶。再过去一年,四年到了,你会发现正好是14050,和样例一样。但我还是觉得这个题题干有问题,他明明问的是收益,本来一万块,四年翻了一倍多?(我也去买)所以我觉得样例改成4050,最后结果再减去一开始的钱数,才符合这个题的题干叙述。

代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath> using namespace std; int m,ans,n,d,v[100001],w[100001]; int f[100001]; int main() { cin>>m;//输入的是几组测试数据 while(m--) { cin>>ans>>n;//输入的是你一共有多少钱和你要存几年 cin>>d;//这个是有几种债券可以买 for(int i=1;i<=d;i++) cin>>v[i]>>w[i];//输入价格和价值 for(int k=1;k<=n;k++)//因为你不仅要存一年,所以要循环每一年的操作 { for(int i=1;i<=d;i++)//以下就是完全背包,因为只要你有钱,一种债券你可以一直买 for(int j=v[i];j<=ans;j++)//循环背包体积,一维的f数组只需要从每种债券的价格(体积)开始循环就行,因为你如果没那么多钱你也买不到它。这里其实可以优化一下下,因为他说价值都是一千的倍数,所以可以j+=1000,也没问题,其实要是这样的话可以直接把f数组开小,输入进来的数除以1000,然后再加就可以了,这样既可以降低空间复杂度也可以降低时间复杂度 f[j]=max(f[j-v[i]]+w[i],f[j]);//如果买了能得到更多钱,那当然果断买!!!! ans+=f[ans];//你赚完一年钱之后要加入你的总资产,然后去买更多的债券,去挣更多的钱 memset(f,0,sizeof(f));//这里也是细节操作,你要请空f数组,因为每一年都是重新操作 } cout<<ans<<endl;//最后只要输出你现在手里有多少钱就行了(题目里说的是收益,读不懂题也不能怪我) } return 0; }

 

posted @ 2020-05-25 15:42  徐明拯  阅读(186)  评论(0编辑  收藏  举报