P1108 低价购买
题意:给出n个数,求最长下降子序列,求不同最长下降子序列的方案数
相同方案的定义为:长度相同并且有元素相同 比如这样一个序列 9 7 6 5 5
(9 7 6 5) (9 7 6 5) 这两个5的下标分别为4 5 ,但是这样的序列是相同的
思路:首先我们求出最长下降子长度
在求出前i个数的最长下降子序列长度后
我们就开始遍历求方案数
那么如何求方案数呢?
当满足 dpx[j]+1==dpx[i]&&a[j]>a[i] 时,即可dpy[i]+=dpy[j];
但是这样做后,还会剩下重复的方案
假如出现 a[j]==a[i]&&dpx[i]==dpx[j] 时,dpy[j]=0;即可
最后通过更新出来的最长序列长度来枚举一遍,在此长度下的方案数即可
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=5e3+10; 4 int dpx[maxn]; 5 int dpy[maxn]; 6 int a[maxn]; 7 int main() 8 { 9 int n; 10 scanf("%d",&n); 11 for(int i=1;i<=n;i++) 12 scanf("%d",&a[i]); 13 int mx=1; 14 for(int i=1;i<=n;i++){ 15 for(int j=i-1;j>=1;j--){ 16 if(a[j]>a[i]) 17 dpx[i]=max(dpx[i],dpx[j]+1); 18 } 19 if(!dpx[i]) dpx[i]=1; 20 for(int j=1;j<i;j++){ 21 if(a[j]==a[i]&&dpx[i]==dpx[j]) 22 dpy[j]=0; 23 else if(dpx[j]+1==dpx[i]&&a[j]>a[i]) 24 dpy[i]+=dpy[j]; 25 } 26 if(!dpy[i]) dpy[i]=1; 27 mx=max(mx,dpx[i]); 28 } 29 int ans=0; 30 for(int i=1;i<=n;i++) 31 if(dpx[i]==mx) 32 ans+=dpy[i]; 33 printf("%d %d\n",mx,ans); 34 return 0; 35 }