hdoj4833Best Financing【dp】

来源:互联网 发布:网络订票在代办点取票 编辑:程序博客网 时间:2024/04/29 16:02



Best Financing

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


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
21 21 100001 100 550 200 102 21 100005 200001 5 65 9 7
 

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

#include<cstdio>#include<cstdlib>#include<cstring>using namespace std;const int maxn=100010;double MAX(double a,double b){return a>b?a:b;}double dp[maxn];int head[maxn],earning[maxn];struct Node{int start,end,inter;int next;}A[maxn];int main() {int t,n,m,i,j,k=1;scanf("%d",&t);while(t--){scanf("%d%d",&n,&m);memset(dp,0,sizeof(dp));memset(head,-1,sizeof(head));memset(earning,0,sizeof(earning));for(i=0;i<n;++i){int date,val;scanf("%d%d",&date,&val);earning[date]+=val;//date有重复 }int a,b,c;for(i=0;i<m;++i){scanf("%d%d%d",&a,&b,&c);A[i].start=a;A[i].end=b;A[i].inter=c;A[i].next=head[a];head[a]=i;}double ans=0;for(i=100000;i>=1;--i){dp[i]=dp[i+1];for(j=head[i];j!=-1;j=A[j].next){dp[i]=MAX(dp[i],dp[A[j].end]+A[j].inter);//dp[i]表示从第i天到最后一天收益利率和的最大值 }ans+=dp[i]*earning[i];//依次算出将第i天的本金存入到最后一天的最大值; }printf("Case #%d:\n%.2lf\n",k++,ans/100.0);}return 0;}
0 0
原创粉丝点击