Poj 2063 Investment

題目

Poj 2063 Investment

Description
John never knew he had a grand-uncle, until he received the notary's letter. He learned that his late grand-uncle had gathered a lot of money, somewhere in South-America, and that John was the only inheritor. 
John did not need that much money for the moment. But he realized that it would be a good idea to store this capital in a safe place, and have it grow until he decided to retire. The bank convinced him that a certain kind of bond was interesting for him. 
This kind of bond has a fixed value, and gives a fixed amount of yearly interest, payed to the owner at the end of each year. The bond has no fixed term. Bonds are available in different sizes. The larger ones usually give a better interest. Soon John realized that the optimal set of bonds to buy was not trivial to figure out. Moreover, after a few years his capital would have grown, and the schedule had to be re-evaluated. 
Assume the following bonds are available: 
Value   Annual
interest
4000
3000    400
250

With a capital of e10 000 one could buy two bonds of $4 000, giving a yearly interest of $800. Buying two bonds of $3 000, and one of $4 000 is a better idea, as it gives a yearly interest of $900. After two years the capital has grown to $11 800, and it makes sense to sell a $3 000 one and buy a $4 000 one, so the annual interest grows to $1 050. This is where this story grows unlikely: the bank does not charge for buying and selling bonds. Next year the total sum is $12 850, which allows for three times $4 000, giving a yearly interest of $1 200. 
Here is your problem: given an amount to begin with, a number of years, and a set of bonds with their values and interests, find out how big the amount may grow in the given period, using the best schedule for buying and selling bonds.

Input
The first line contains a single positive integer N which is the number of test cases. The test cases follow. 
The first line of a test case contains two positive integers: the amount to start with (at most $1 000 000), and the number of years the capital may grow (at most 40). 
The following line contains a single number: the number d (1 <= d <= 10) of available bonds. 
The next d lines each contain the description of a bond. The description of a bond consists of two positive integers: the value of the bond, and the yearly interest for that bond. The value of a bond is always a multiple of $1 000. The interest of a bond is never more than 10% of its value.
Output

For each test case, output – on a separate line – the capital at the end of the period, after an optimal schedule of buying and selling.

Sample Input
1
10000 4
2
4000 400
3000 250

Sample Output
14050

具體的內(nèi)容就是一共有多組債券,分別給出了每組債券的價格與每年的利息,然后根據(jù)投資的年數(shù)與投資的初始錢數(shù),計(jì)算最終的總價值。
輸入:
N(測試數(shù)據(jù)數(shù)量)
amount(初始錢數(shù)) years(年數(shù))
d(債券數(shù)量)
value(債券價格) interest(每年的利息)
...(一共 d 組)

思路

核心其實(shí)還是背包問題,關(guān)鍵有幾個點(diǎn):

  1. 初始錢數(shù)最大為 1000000,年數(shù)最大為 40,利息最大為 10%,有此我們可以計(jì)算出最終的結(jié)果最大約為 45260000,按照背包的思路,如果直接開這么大的數(shù)據(jù)內(nèi)存就直接爆掉了,而題目給了每組債券都是 1000 的整數(shù)倍,所以 1000 以下的部分其實(shí)跟利息的計(jì)算是毫無關(guān)系的(僅僅是每年喲),而 1000 以上的部分可以直接通過除掉 1000 來減小數(shù)組的大小,這樣數(shù)組其實(shí)開到 45260 就可以了。
  2. 先暴力計(jì)算出所有可能金錢得到的利息數(shù)(即 result[]),這樣在以后每年計(jì)算的時候都可以直接取值就可以了
  3. 剩下的問題就是計(jì)算 result[] 了,標(biāo)準(zhǔn)的背包問題,這里我就不細(xì)說了,如果不了解的話直接看《背包九講》吧。

代碼

// http://poj.org/problem?id=2063
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <cstring>
#include<math.h>
using namespace std;

#define max(x,y) (x > y ? x : y)

//債券
struct Bond {
    // 債券的價格
    int value;
    
    // 債券的利息
    int interest;
};

// 債券的總列表
Bond bondList[15];

// index 代表金額(除以 1000 后的值),result[index] 為這個金額最大的利息數(shù)
int result[50000];

/**
 * 根據(jù)債券的信息,更新 result 數(shù)據(jù)
 **/
void updateResult(int maxAmount, int boudNum) {
    for (int i = 0; i < boudNum; i++) {
        int value = bondList[i].value;
        int interest = bondList[i].interest;
        
        int lastMax = 0;
        for(int t = 0; t <= maxAmount - value; t++) {
            if (result[t] != 0) {
                lastMax = result[t];
            }
            result[t + value] = max(result[t + value], result[t] + interest);
            if (result[t] == 0) {
                result[t] = lastMax;
            }
        }
    }
}

/**
 * 根據(jù) updateResult 計(jì)算出來的結(jié)果,計(jì)算最終結(jié)果
 **/
int calculate(int amount, int years) {
    int total = amount;
    for(int i = 0; i < years; i++) {
        total += result[total / 1000];
    }
    return total;
}

int main(int argc, const char * argv[]) {
    
    // 處理輸入數(shù)據(jù),不多解釋
    int n, amount, years, boudNum;
    scanf("%d", &n);
    
    for (int i = 0; i < n; i++) {
        scanf("%d %d %d", &amount, &years, &boudNum);
        for (int t = 0; t < boudNum; t++) {
            scanf("%d %d", &bondList[t].value, &bondList[t].interest);
            // 因?yàn)閭膬r格都是 1000 的整數(shù)倍,所以這里可以除掉 1000
            bondList[t].value /= 1000;
        }

        // 初始化數(shù)據(jù),避免每個 testcase 互相影響
        memset(result, 0, sizeof(result));
        
        // 復(fù)利,每年最高 10%,可以計(jì)算出最大的可能結(jié)果,剪枝,避免過多的計(jì)算
        int maxAmount = ((int)(pow(1.1, years) * amount / 1000) + 1);
        
        updateResult(maxAmount, boudNum);
        printf("%d\n", calculate(amount, years));
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 著名財(cái)經(jīng)雜志《財(cái)富》對本書的評論是:如果你一生只讀一本關(guān)于投資的著作,無疑就是這本《聰明的投資者》。 首先介紹一下...
    惜她閱讀 6,976評論 0 34
  • Less is more.(“少即是多”) 在過去物質(zhì)匱乏的年代,不斷做物質(zhì)加法——為家里添置冰箱,買回電視機(jī),配...
    王英的簡書閱讀 335評論 0 0
  • 張愛玲說,出名要趁早,來得太晚的話,快樂也不那么痛快。 其實(shí),吃虧也要趁早,別等到太晚,連重來的機(jī)會都沒有。 1 ...
    阿春牧羊犬閱讀 6,695評論 49 122
  • 那一年你是否會選擇我,青澀懵懂的我第一次出現(xiàn)在你的面前顯得那么的靦腆。 "誒,同學(xué),請問新生報(bào)到處在哪里啊?"陳莫...
    fd6db1c70418閱讀 451評論 1 1