题意:
给一串数字,求最大的严格下降子序列,且还有求出这种序列的个数。
但是同时要注意重复序列只算一个。
比如 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;
}