POJ 1952 BUY LOW, BUY LOWER DP 最长下降序列求个数

注意:重复的只算一次

如何去掉一些重复的是本题的关键

我的去重思路:

7

5 3 7 6 3 2 1

6

5 3 7 3 1

5

5 3 2 1 3

第一组在推到 数字 2 的时候有 3会出现重复, 显然前面一个3是可有可无的。

第二组也一样,前面一个3是可有可无的。

1.如果最长下降序列中有后面一个3, 如第一二组数据,那么前面一个3是无用的,在推好后面一个3之后把之前的所用重复的计数数组清零

2.如果最长下降序列中只有前面一个3,如第三组数据, 做情况1的操作也是不会影响结果的,因为第三组的前面一个3的状态已经推到2后才被清零的。

View Code
#include<stdio.h>
#include<string.h>
bool vis[5003];
int a[5003], dp[5003], cnt[5003];
int main()
{
    int i, j, k, max, n;
    while( ~scanf("%d", &n))
    {
        int id = 0;
        for(i = 1; i <= n; i++)
            scanf("%d", &a[i]);
        memset(dp, 0, sizeof(dp));
        memset(cnt, 0, sizeof(cnt));
        int max = 0;
        for(i = 1; i <= n; i++)
        {
            //求长度
            k = 0;
            for(j = 1; j < i; j++)
                if(a[i] < a[j] && dp[k] < dp[j])
                    k = j;
            dp[i] = dp[k] + 1;
            if(max < dp[i]) max = dp[i];

            //求个数
            if(dp[i] == 1) cnt[i] = 1;
            else
            {
                for(j = 1; j < i; j++)
                    if(dp[j] + 1== dp[i] && a[i] < a[j])
                        cnt[i] += cnt[j];
            }
            for(j = 1; j < i; j++)
                if(a[i] == a[j])
                    cnt[j] = 0;
        }
        int ans = 0;
        for(i = 1; i <= n; i++)
            if(max == dp[i]) ans += cnt[i];
        printf("%d %d\n", max, ans);
    }
    return 0;
}

 

posted @ 2012-11-15 22:02  To be an ACMan  Views(398)  Comments(0)    收藏  举报