12 68 69 54 70 68 64 70 67 78 62 98 87
4 4
//最难的就是要求出方案数,用num[i]表示到第i个数的最长下降子序列有几种方案数。在扫描[1,i-1]寻找最优解,如果当前解与已知解相同就进行累加,第二重循环j应该从i-1到1逆序循环因为越靠近最优解的会有不少于靠前的方案数。
#include<cstdio>
#include<cstring>
int price[5001],num[5001],dp[5001];
int main()
{
    int n,i,j,t;
    while(scanf("%d",&n)!=EOF)
    {
        memset(dp,0,sizeof(dp));
        memset(num,0,sizeof(num));
        memset(price,0,sizeof(price));
        for(i=0;i<n;i++)
            scanf("%d",&price[i]);
        for(i=0;i<=n;i++)
        {
            t=1<<30;
            num[i]=1;
            for(j=i-1;j>=0;j--)
            {
                if(price[j]>price[i])
                {
                    if(dp[j]>=dp[i])
                    {
                        t=price[j];
                        dp[i]=dp[j]+1;
                        num[i]=num[j]; //同一最长下降只序列方案数相同
                    }
                    else if(dp[j]+1==dp[i]&&price[j]<t)  //保证是最长下降子序列并且不会重复
                    {
                        t=price[j];
                        num[i]+=num[j];
                    }
                }
            }
        }
        printf("%d %d\n",dp[n],num[n]);
    }
    return 0;
}
 
原文:http://blog.csdn.net/u012773338/article/details/38272573