Investment

题目链接:

https://vjudge.net/contest/348156#problem

题面:

在这里插入图片描述
在这里插入图片描述

翻译:

约翰直到收到公证人的信,才知道他有个叔父。他知道他已故的叔父在南美某地收集了很多钱,约翰是唯一的继承人。
约翰暂时不需要那么多钱。但他意识到,最好把这笔资金存放在一个安全的地方,让它增长,直到他决定退休。银行使他相信某种债券对他来说很有趣。
这种债券有固定的价值,每年的利息是固定的,在每年年底付给所有人。债券没有固定期限。债券有不同大小。大一点的通常会有更好的兴趣。很快,约翰意识到,要买一套最优的债券并不容易。此外,几年后,他的资本会增加,必须重新评估时间表。
假设以下债券可用:
年度价值
兴趣
四千
3000 400个
250个
如果资本金为10万欧元,一个人可以购买两张4000美元的债券,年利息为800美元。买两张3000美元的债券,其中一张4000美元是个更好的主意,因为它每年给900美元的利息。两年后,资本金已经增长到11800美元,卖出3000美元,买入4000美元是有道理的,因此年利息增长到1050美元。这就是这个故事不太可能发生的地方:银行不收取买卖债券的费用。明年的总额是12850美元,相当于4000美元的三倍,年利息是1200美元。
这就是你的问题:给定一个开始的数额,若干年,以及一组有其价值和利益的债券,利用买卖债券的最佳时间表,找出该数额在给定时期内可能增长多少。

输入:

第一行包含一个正整数N,它是测试用例的数量。接下来是测试用例。
测试用例的第一行包含两个正整数:开始的金额(最多100000美元),资本可能增长的年数(最多40年)。
下一行包含一个数字:可用债券的数字d(1<=d<=10)。
接下来的d行每一行都包含一个键的描述。债券的描述由两个正整数组成:债券的价值和债券的年利息。债券的价值总是1000美元的倍数。债券的利息不超过其价值的10%

输出:

对于每个测试用例,在一个最优的买卖计划之后,在一个单独的行上输出期末的资本。

思路:

首先这道题目是要找一个最优的买卖计划,所以这就是一个背包问题,而这里与最简单的01背包的不同的地方为它这里增长的年数是有很多年的,像如果第一次取到最优的买卖计划,这时候得到的利息加上本金就显然成为了下一年的本金,就这一点不同,而需要实现这一点就只需要3重for循环来实现,我们先找出最优的买卖计划,然后得出之后,下一年的本金就变为上一年的本金加上最优计划得到的利息,再来查找最优买卖计划,这样子就可以得到最后的总本金(注:这道题目题目数据较大,所以我们要把债券的价值和总本金都除以1000来优化计算量,从而使程序更加高效)

参考代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<algorithm>
using namespace std;
int main()
{
    long long t;
    scanf("%lld",&t);
    while(t--)
    {
        long long n,y,m,z,j,sum,i;
        long long w[50000];
        long long v[50000];
        long long dp[50000];
        scanf("%lld%lld",&n,&y);
        scanf("%lld",&m);
        for(i=0;i<m;i++)
        {
            scanf("%lld%lld",&w[i],&v[i]);
            w[i]=w[i]/1000;//因为债券的价值总是1000美元的倍数,所以我们就可以一开始就把债券的价值除以1000美元,来减少计算量
        }
        memset(dp,0,sizeof(dp));//每次都需要将dp记录的值清空才行
        sum=n;
        for(z=0;z<y;z++)//这里进行的是有y年,我们可以存款y次
        {
            n=sum/1000;//同样除以1000来减少程序的计算量
            for(i=0;i<m;i++)
            {
                for(j=w[i];j<=n;j++)
                {
                    dp[j]=max(dp[j],dp[j-w[i]]+v[i]);//这里面就是一个经典的01背包的代码,不多说了
                }
            }
            sum=sum+dp[n];//每年存款完了之后,本金就变为之前的本金加上存储的利息,所以就要加上dp[n]。
        }
        printf("%lld\n",sum);
    }
}

发布了55 篇原创文章 · 获赞 12 · 访问量 8981

猜你喜欢

转载自blog.csdn.net/qq_45740533/article/details/103519026