低价购买(cogs2724)

这个题主要分为两个部分,一个是求严格的最长下降子序列,还有就是求方案数,第一个问题超简单,不用说,第二个算法有些困难,所以在此贴代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=5010;
int n,a[maxn],f[maxn],b[maxn];
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		f[i]=1;
	}
	int ans=1,tot=0;
	for(int i=2;i<=n;i++)
	{
		for(int j=1;j<i;j++)
			if(a[j]>a[i]) f[i]=max(f[i],f[j]+1);
		ans=max(ans,f[i]);
	}
	for(int i=1;i<=n;i++)
	{
		if(f[i]==1) b[i]=1;//这个很重要,说明只有一个数的时候就应该方案数为1 
		for(int j=1;j<i;j++)
		{
			if((f[i]==f[j]+1)&&a[j]>a[i]) b[i]+=b[j];
			if(f[i]==f[j]&&a[j]==a[i]) f[j]=0;//如果两个数相等,并且序列长度也相等的时候,使前面的消失 
		}	
	}
	for(int i=1;i<=n;i++) if(f[i]==ans) tot+=b[i];//这个语句不能写在上面,因为你在上面有时会重置fi,所以必须重新循环 
	printf("%d %d",ans,tot);
}

/**
12
68 69 54 64 68 64 70 67 78 62 98 87

5
62 62 68 85 100
**/

 

posted @ 2017-07-06 15:40  xinyimama  阅读(69)  评论(0编辑  收藏  举报