POJ 1952 BUY LOW,BUY LOWER 最长递减子序列 动态规划

POJ 1952 BUY LOW,BUY LOWER

题目描述:

  题目链接:POJ 1952 BUY LOW,BUY LOWER
  

题目大意:

  题目背景是股市,要求在给定的价格序列中求每次购买价格都下降的最长的购买次数以及购买方案数。即求最长递减子序列的长度,已经相同长度序列的个数。

解题思路:

  第i项为当前比较项,第j项是i项之前的某一项。

  若满足 prices[i]<prices[j] , 则 maxlen[i] 的值满足状态转移方程:

  • maxlen[i]=max(maxlen[i],maxlen[j]+1)

  同时,最长递减子序列的个数 maxnum[i]

  • maxlen[j]+1>maxlen[i] 时, maxnum[i]=max[j] ;
  • maxlen[j]+1==maxlen[i] 时, maxnum[i]+=maxnum[j] ;

  特别的当 prices[i]==prices[j] ,为防止重复计数跳出循环。同时当 maxlen[i]==1 时,即当前重复的数字并没有对最大链长做出贡献,故将 maxnum[i] 置为 0

复杂度分析(最近正在学,有错请指出):

时间复杂度 O(n2)
空间复杂度 O(n)

AC代码:

#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>

using namespace std;
const int maxn = 5100;
int prices[maxn];
int maxlen[maxn];
int maxnum[maxn];

int main(){
    int N;
    while(scanf("%d",&N) != EOF){
        for(int i = 0; i < N; i++){
            scanf("%d" ,&prices[i]);
            maxlen[i] = 1;
            maxnum[i] = 1;
        }
        for(int i = 1; i < N; i++)
            for(int j = i - 1; j >= 0; j--){
                if(prices[i] < prices[j]){
                    if(maxlen[j] + 1 > maxlen[i]){
                        maxlen[i] = maxlen[j] + 1;
                        maxnum[i] = maxnum[j];
                    }
                    else if(maxlen[i] == maxlen[j] + 1){
                        maxnum[i] += maxnum[j];
                    }
                }
                else if(prices[i] == prices[j]){
                    if(maxlen[i] == 1) maxnum[i] = 0;
                    break;
                }
            }
        int anslen = 0,ansnum = 0;
        for(int i = 0; i < N; i++)
            if(maxlen[i] > anslen) anslen = maxlen[i];
        for(int i = 0; i < N; i++)
            if(maxlen[i] == anslen) ansnum += maxnum[i];
        printf("%d %d\n", anslen, ansnum);

    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值