低价购买

低价购买
总时间限制: 1000ms 内存限制: 65536kB
描述
“低价购买”这条建议是在股票市场取得成功的一半规则。要想被认为是伟大的投资者,你必须遵循以下购买建议:“低价购买,再低价购买”。每次购买一支股票,你必须用比低于你上次购买的价格购买它。买的次数越多越好!你的目标是遵循以上建议的前提下,求你最多能购买股票的次数。你将被给出一段时间内一支股票每天的出售价(2^16范围内的正整数),你可以选择哪些天购买这些股票。每次购买必须遵循“低价购买,再低价购买”的原则。写一个程序计算最大购买的次数。 这里是某支股票的价格清单: 日期 1 2 3 4 5 6 7 8 9 10 11 12 价格 68 69 54 64 68 64 70 67 78 62 98 87 最优秀的投资者可以购买最多四次股票,可行方案中的一种是: 日期 1 2 3 4 5 6 7 8 9 10 11 12 价格 68 69 54 64 68 64 70 67 78 62 98 87
输入
输入共两行,第1行:N(1≤N≤5000),股票发行天数;
第2行:N个数,是每天的股票价格。
输出
输出文件仅一行,包含两个数:最大购买次数和拥有最大购买次数的方案数(≤2^31),当两种方案“看起来一样时”(就是说它们构成的价格队列一样的时候),这两种方案被认为是相同的。


分析:
根据题目,本题是求一个最长不上升的子序列,但重点是遇见相同的价格,如何选择。仔细分析一下,选择了靠后的相同价格,因为在上一个价格之间与这个价格之间,包含的可能性最多。


#include<iostream>
using namespace std;
int n,dp[5001][5];
int main() {
    cin>>n;
    for(int i = 1; i<=n; i++) {
        cin>>dp[i][0];
        dp[i][1] = 1;
    }
    int l = 0,k = 0;
    for(int i = 1; i<=n; i++) {          //前面没有更大的,从自己开始
        l = 0;
        for(int j = 1; j<i; j++) {
            if(dp[j][0] > dp[i][0]) {
                l++;
            }
        }
        if(l == 0) {
            dp[i][2] = 1;
        }
    }
    for(int i = 2; i<=n; i++) {
        l = 0;
        k = 0;
        for(int j =  1; j<i; j++) {            //最长不上升序列
            if(dp[j][0] > dp[i][0] && dp[j][1]>l) {
                l = dp[j][1];
            }
        }
        if(l) {
            dp[i][1] += l;
        }
        for(int j = 1;j<i;j++){
            if(dp[j][0] == dp[i][0]){
                dp[j][2] = 0;
            }
        }
        for(int j = 1;j<i;j++){
            if(dp[j][0] > dp[i][0] && dp[j][1] + 1 == dp[i][1]){          //判断来源
                dp[i][2] += dp[j][2];
            }
        }
    }
    int maxn = 0;
    for(int i = 1; i<=n; i++) {
        maxn = max(maxn,dp[i][1]);
    }
    cout<<maxn<<" ";
    int ans = 0;
    for(int i = 1; i<=n; i++) {
        if(dp[i][1] == maxn) {
            ans += dp[i][2];
        }
    }
    cout<<ans;
    return 0;
}
posted @ 2017-12-19 22:49  WenOI  阅读(138)  评论(0编辑  收藏  举报
水波背景