POJ1952 BUY LOW, BUY LOWER DP

题意:

给一串数字,求最大的严格下降子序列,且还有求出这种序列的个数。

但是同时要注意重复序列只算一个。

比如 5 5 4 4 3,只有一种5 4 3.答案是3 1. 

思路:

对于严格单调子序列。算是很简单了吧。直接O(N^2)的复杂度实现即可。

至于找次数,其实本质也是DP,具体见代码。


#include<iostream>
#include<algorithm>
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
using namespace std;
const int N=5005;
int n;
int seq[N];//
int dp[N];//找最大长度
int v[N];//找最大长度时的个数
int main()
{
	while(scanf("%d",&n)!=EOF)
	{
		memset(seq,0,sizeof(seq));
		for(int i=1;i<=n;i++)
			scanf("%d",seq+i);
		memset(dp,0,sizeof(dp));
		memset(v,0,sizeof(v));
		v[0]=1;
		for(int i=1;i<=n;i++)
		{
			int mx=0;
			for(int j=i-1;j>=1;j--)
			{
				if(seq[i]<seq[j])
				{
					if(mx<dp[j])
					{
						mx=dp[j];
						v[i]=v[j];
					}
					else if(mx==dp[j])
					{
						v[i]+=v[j];//当dp值相等时,同时seq[i]!=seq[j],所以次数要相加。
					}
				}
				else if(seq[i]==seq[j])//当seq值相等时,排在前面的实际上已经无效了因为后面的肯定更优,所以v值置位0,因为序列相同时次数不叠加。
				{
					v[j]=0;
				}
			}
			dp[i]=mx+1;
			if(!mx)
				v[i]=1;
		}
		int ansa=0,ansb=0;
		for(int i=1;i<=n;i++)
		{
			if(dp[i]>ansa)
			{
				ansa=dp[i];
				ansb=v[i];
			}
			else if(dp[i]==ansa)
			{
				ansb+=v[i];
			}
		}
		printf("%d %d\n",ansa,ansb);
	}
	return 0;
}



你可能感兴趣的:(POJ1952 BUY LOW, BUY LOWER DP)