POJ 1952 BUY LOW, BUY LOWER

传送门:http://poj.org/problem?id=1952

题意:给你n个数,计算最长下降子序列的个数(并且不能重复)例如 5 3  5 3 该序列中 最长下降子序列的个数只有一个

思路:长度的话用dp[i]=max(dp[i],dp[j]+1)进行转移复杂度n^2关键是去重这一步如何计算。另外开一个f数组,表示以 i

 为结尾的最长下降子序列的个数,然后在更新dp[i]的时候,更新数组f,详细注释见代码块了

#include<iostream>
#include<cstdio>
using namespace std;
int num[5005];
int dp[5005];//dp代表以i结尾的最长下降子序列的长度
int f[5005];//f代表 以i为结尾的最长下降子序列的个数
int main()
{
    int n;
    cin >> n;
    for(int i = 0; i < n; i++)
    {
        cin >> num[i];
    }
    int ans = 0;
    int cnt = 0;
    for(int i = 0; i < n; i++)
    {
        dp[i] = 1;
        for(int j = 0; j < i; j++)
        {
            if(num[i] < num[j])
            {
                dp[i] = max(dp[i], dp[j] + 1);
            }
        }
        ans = max(dp[i], ans);
        if(dp[i] == 1) //表示i点处只有num[i]一个元素  所有也只有这一个序列即是f[i]=1;
        {
            f[i] = 1;
        }
        for(int j = 0; j < i; j++)
        {
            if(num[i] == num[j]) //  进行去重了  表示只使用num[i]这个元素了  把其他相同的元素舍去了
                f[j] = 0;
        }
        for(int j = 0; j < i; j++)
        {
            if(num[i] < num[j] && dp[i] == dp[j] + 1)
            {
                f[i] += f[j]; // 对以i为结尾的序列的个数 进行更新
            }
        }
    }
    cout << ans << " ";
    for(int i = 0; i < n; i++)
    {
        if(ans == dp[i])
        {
            cnt += f[i];
        }
    }
    cout << cnt << endl;
}
原文地址:https://www.cnblogs.com/yyaoling/p/12260426.html