poj 1952 最长递减子序列+求个数

来源:互联网 发布:mac怎么启用flash 编辑:程序博客网 时间:2024/06/06 01:20

题意:给出N个数的序列,求最长递减子序列,并且求出不同的序列方案个数。

解释:如 4 3 2 4 3 2这个序列,最长递减子序列长度显然为3,但是个数只计算一次,因为前后两个都是4 3 2,看做是相同的。

思路:计数搞不定,看的别人题解。num[i]表示前i个数的序列中,达到最长递减(以s[i]为最后一位)的而且该序列方案中前一个数在s[j]之后的方案个数。其中s[j]为最靠右的=s[i]的数字。这样便把重复的分来计数了。

#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <algorithm>#include <queue>using namespace std;#define INF 0x3fffffff#define clr(s,t) memset(s,t,sizeof(s))#define N 5005int s[N],num[N],dp[N],n;int main(){    int i,j,sum=0,res = 0;    scanf("%d",&n);    for(i = 1;i<=n;i++){        scanf("%d",&s[i]);        dp[i] = num[i] = 1;    }    for(i = 2;i<=n;i++){        for(j = i-1;j>=1;j--){            if(s[j] > s[i]){                if(dp[j] >= dp[i]){                    dp[i] = dp[j]+1;                    num[i] = num[j];                }else if(dp[j]+1 == dp[i]){                    num[i] += num[j];                }            }else if(s[j]==s[i]){                if(dp[i] == 1)                    num[i] = 0;                break;            }        }    }    for(i = n;i>=1;i--)        res = max(res,dp[i]);    for(i = n;i>=1;i--)        if(dp[i] == res)            sum += num[i];    printf("%d %d\n",res,sum);    return 0;}


0 0
原创粉丝点击