POJ 1952 求最长下降子序列的长度和个数

The advice to "buy low" is half the formula to success in the bovine stock market.To be considered a great investor you must also follow this problems' advice: 

                    "Buy low; buy lower"


Each time you buy a stock, you must purchase it at a lower price than the previous time you bought it. The more times you buy at a lower price than before, the better! Your goal is to see how many times you can continue purchasing at ever lower prices.

You will be given the daily selling prices of a stock (positive 16-bit integers) over a period of time. You can choose to buy stock on any of the days. Each time you choose to buy, the price must be strictly lower than the previous time you bought stock. Write a program which identifies which days you should buy stock in order to maximize the number of times you buy. 

Here is a list of stock prices: 

 Day   1  2  3  4  5  6  7  8  9 10 11 12

Price 68 69 54 64 68 64 70 67 78 62 98 87



The best investor (by this problem, anyway) can buy at most four times if each purchase is lower then the previous purchase. One four day sequence (there might be others) of acceptable buys is: 

Day    2  5  6 10

Price 69 68 64 62

Input

* Line 1: N (1 <= N <= 5000), the number of days for which stock prices are given 

* Lines 2..etc: A series of N space-separated integers, ten per line except the final line which might have fewer integers. 

Output

Two integers on a single line: 
* The length of the longest sequence of decreasing prices 
* The number of sequences that have this length (guaranteed to fit in 31 bits) 

In counting the number of solutions, two potential solutions are considered the same (and would only count as one solution) if they repeat the same string of decreasing prices, that is, if they "look the same" when the successive prices are compared. Thus, two different sequence of "buy" days could produce the same string of decreasing prices and be counted as only a single solution. 

Sample Input

12
68 69 54 64 68 64 70 67 78 62
98 87

Sample Output

4 2

这题要求最长下降子序列的长度和个数

先上代码解释吧

借用大佬的思想:我是用这个推论解的:一个数列,比如5,3,1,5,3,1;把它假想成inf,5,3,1,5,3,1(多了一个inf);对于inf来说,只能用inf推出第一个5,同理只能用第一个5推出第一3,当然,我们也可以用第二个5推出第二个3,但是因为没有东西可以推出第二个5,所以不存在一个从起点到第二个3的途径。这样就避免了重复计算。它的本质是贪心。即遇到两个位置不同的5,如果这两个5的前面的数是一样的,则能由第二个5推出来的一定能由第一个5推出来;如果前面的数有不一样的,则这两个5都能被推出来。

#include<stdio.h>
int a[5001];
int ans1,ans2;
int sum[5001],len[5001];
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        int i,j;
        for(i=1;i<=n;i++)
            scanf("%d",a+i);
        ans1=ans2=0;
        for(i=1;i<=n;i++)
        {
            len[i]=1;//最长递减子序列的长度
            sum[i]=1;//最长递减子序列个数
            for(j=i-1;j>=1;j--)
            {
                if(a[i]<a[j])//核心
                {
                    if(len[i]==len[j]+1)//若if语句成立,就说明a[i]与a[j]在同一个下降序列当中
                        sum[i]+=sum[j];//因此我们只需要只需要将每一种满足要求的状态转移到sun[i]就行,就比如 68 69 54 sum[3]=2,因为lend[3]=2,len[1]=1,这不就说明长度为2的递减序列有2个
                    else if(len[i]<len[j]+1)
                    {
                        len[i]=len[j]+1;
                        sum[i]=sum[j];
                    }
                }
                if(a[i]==a[j])
                {
                    if (len[i]==1)//只有一个,那么就需要将sum[i]置为0,不需要重复计算
                    sum[i]=0;break;//既然只有一个元素,置0就不需要继续往下循环了
                }//重复的单个元素肯定是需要移除的
            }
            if(ans1<len[i])
                ans1=len[i];
        }
        for(i=1;i<=n;i++)
        if(ans1==len[i])
        ans2+=sum[i];
        printf("%d %d\n",ans1,ans2);
    }
    return 0;
}

参考

猜你喜欢

转载自blog.csdn.net/c___c18/article/details/82556905