简单说一下题意,就是求最长递减子序列,并且!!!求出总共有多少个不同的最长子序列,比如
9
99 100 97 100 97 100 101 98 96
这组样例中的最长递减子序列长度为3,
(用pi表示位于第i个)
p2,p3,p9和p2,p5,p9和p4,p5,p9就只能算一个(因为都是100,97,96)。
刚做这道题也是没有什么思路,就直接先敲代码实现全部最长子序列个数(包括相同的),以下是这个的主要实现部分(非正确解法,要改进)
if(dp[i]!=1) cnt[i]=0;这个就是如果最长子序列不是1,那么它肯定是从前面来的,先置零
for(int i=2;i<=n+1;i++)
{
for(int j=1;j<i;j++)
if(price[j]>price[i]&&dp[i]<dp[j]+1) dp[i]=dp[j]+1;
if(dp[i]!=1) cnt[i]=0;
int tmp=0,tnt=0;
for(int j=1;j<i;j++)
if(price[j]>price[i]&&dp[i]==dp[j]+1)
cnt[i]+=cnt[j];
为什么讲这个呢?因为我发现只要在这个代码上改进以下就能得到ac代码。
注意,如果dp[i]是从前面来的,如果出现重复(比如上面i=9,重复就是3和5),那么一定!!!一定3和5一定是可能答案(比如这里的100 就不是可能答案,因为dp[4]=1,dp[4]
int tmp=0,tnt=0;
for(int j=1;j<i;j++)
{
if(price[j]>price[i]&&dp[i]==dp[j]+1)
{ if(tmp!=price[j]) {cnt[i]+=tnt;tnt=0;}
tnt=max(tnt,cnt[j]);tmp=price[j];}
}
cnt[i]+=tnt;
如果觉得写的好,麻烦点一下赞,想了一个半小时。
ac代码
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <vector>
#include <string.h>
#include <queue>
#define ms(X) memset(X,0,sizeof(X))
typedef long long LL;
using namespace std;
int cnt[5005],price[5005],dp[5005];
int main(int argc, char const *argv[])
{
int n;
cin>>n;
for(int i=1;i<=n;i++) scanf("%d",price+i);
price[n+1]=-1,dp[n+1]=cnt[n+1]=0;
for(int i=1;i<=n;i++) cnt[i]=dp[i]=1;
for(int i=2;i<=n+1;i++)
{
for(int j=1;j<i;j++)
if(price[j]>price[i]&&dp[i]<dp[j]+1) dp[i]=dp[j]+1;
if(dp[i]!=1) cnt[i]=0;
int tmp=0,tnt=0;
for(int j=1;j<i;j++)
{
if(price[j]>price[i]&&dp[i]==dp[j]+1)
{ if(tmp!=price[j]) {cnt[i]+=tnt;tnt=0;}
tnt=max(tnt,cnt[j]);tmp=price[j];}
}
cnt[i]+=tnt;
}
printf("%d %d\n",dp[n+1]-1,cnt[n+1] );
return 0;
}