HDU 4833 Best Financing DP

Best Financing

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 120    Accepted Submission(s): 24


php

Problem Description
小 A想經過合理投資銀行理財產品達到收益最大化。已知小A在將來一段時間中的收入狀況,描述爲兩個長度爲n的整數數組dates和earnings,表示在 第dates[i]天小A收入earnings[i]元(0<=i<n)。銀行推出的理財產品均爲週期和收益肯定的,可描述爲長度爲m的三個 整數數組start、finish和interest_rates, 若購買理財產品i(0<=i<m),須要在第start[i]天投入本金,在第finish[i]天可取回本金和收益,在這期間本金和收益都 沒法取回,收益爲本金*interest_rates[i]/100.0。當天取得的收入或理財產品到期取回的本金當天便可購買理財產品(注意:不考慮復 利,即購買理財產品得到的收益不能用於購買後續的理財產品)。假定閒置的錢沒有其餘收益,如活期收益等,全部收益只能經過購買這些理財產品得到。求小A可 以得到的最大收益。

限制條件:
1<=n<=2500
1<=m<=2500
對於任意i(0<=i<n),1<=dates[i]<=100000,1<=earnings[i]<=100000, dates中無重複元素。
對於任意i(0<=i<m),1<=start[i]<finish[i]<=100000, 1<=interest_rates[i]<=100。
 

 

Input
第一行爲T (T<=200),表示輸入數據組數。
每組數據格式以下:
第一行是n m
以後連續n行,每行爲兩個以空格分隔的整數,依次爲date和earning
以後連續m行,每行爲三個以空格分隔的整數,依次爲start, finish和interest_rate
 

 

Output
對第i組數據,i從1開始計,輸出
Case #i:
收益數值,保留小數點後兩位,四捨五入。
 

 

Sample Input
2 1 2 1 10000 1 100 5 50 200 10 2 2 1 10000 5 20000 1 5 6 5 9 7
 

 

Sample Output
Case #1: 1000.00 Case #2: 2700.00
 

 

Source
 
 
 
題目分析:
  
  這裏咱們忽略利率底下的100,將其放在最後計算(由於全部的利益都要除以100,索性放到最後)。
  
  這樣,題目能夠理解爲, 給你n份錢,每份錢有一個價值val[i],每份錢所給的時間以後有x個區間,每一個區間有一個價值w[i],選擇互不相交的區間,這份錢能帶來收益即爲   val[i] *   sum(w[j])(其中全部的j互不相交)。  
  
  全部錢帶來的收益即爲:sum(val[i] * sum(w[j]))(其中全部的j互不相交)。
 
那麼怎麼樣才能使得收益達到最大??
 
設dp[i]爲從第i個時間點開始日後選擇的全部不想交的區間的價值總和的最大值,咱們假設第i個時間點以後的dp[j]已經獲得,那麼dp[i] = max(dp[j])+ w[i];
 
則最大利益即 ans = sum(val[i] * dp[i]) / 100.0;(不要忘了將利率底下的100除掉)
 
這裏咱們用鏈式前向星存儲屬於以每一個時間點爲起點的每一個區間的終點和價值。(並小小的加一個輸入優化玩耍一下~)
 
代碼以下:
 
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define max(a, b) ((a) > (b) ? (a) : (b))
using namespace std;
const int O = 100005;
typedef struct E{
    int v, n, e;
}E;
E edge[O];
int Adj[O], l;
int val[O], dp[O];
int t, n, m, cas;
int d, e, s, f;
void addedge(int u, int v, int e){
    edge[l].v = v; edge[l].e = e; edge[l].n = Adj[u]; Adj[u] = l++;
}
int read(){
    char ch = ' ';
    int x = 0;
    while(ch < '0' || ch > '9') ch = getchar();
    while(ch >= '0' && ch <= '9'){
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x;
}
void work(){
    memset(val, 0, sizeof(val));
    memset(Adj, -1, sizeof(Adj));
    l = 0;
    n = read(); m = read();
    while(n--){
        d = read(); e = read();
        val[d] += e;
    }
    while(m--){
        s = read(); f = read(); e = read();
        addedge(s, f, e);
    }
    dp[100001] = 0;
    double ans = 0;
    for(int i = 100000; i; --i){
        dp[i] = dp[i + 1];
        for(int j = Adj[i]; ~j; j = edge[j].n){
            dp[i] = max(dp[i], dp[edge[j].v] + edge[j].e);
        }
        ans += dp[i] * val[i];
    }
    printf("%.2f\n", ans / 100);
}
int main(){
    for(t = read(), cas = 1; cas <= t; ++cas){
        printf("Case #%d:\n", cas);
        work();
    }
    return 0;
}
HDU 4833
相關文章
相關標籤/搜索