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;
}
發佈了31 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章