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