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(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;
}