洛谷P1108 低价购买 动态规划

洛谷P1108 低价购买
动态规划
题意 求最长下降子序列长度,以及有多少子序列也是这样的长度,完全相同的不算

f[ i ] 表示到第 i 位时最长的下降子序列

t[ i ] 表示 到第i位有多少这样的不相同的 下降子序列

如果 完全相同的也算的话 那么直接状态转移 t[ i ] = t[ i ] + t[ j ]
但是现在完全相同的不算,那么这样怎么算呢,
j < i 如果 f[ j ] == f[ i ] && a[ j ] == a[ i ] 此时 两者方案相同 那么说明 结尾为 a[ j ] 的 最长下降子序列
也包含在 i 的最长下降子序列中,唯一不同的是 在 j--i 这段中 ,可能又增加了一些下降子序列的长度,也就是
说 i位保存的东西比 j 位的要优,那么就直接把 t[ j ] = 0 因为 j 位 已经没用了 答案还是 i 位优

 1 #include <cstdio>
 2 #include <cmath>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <string>
 6 #include <algorithm>
 7 #include <iomanip>
 8 #include <iostream> 
 9 using namespace std ; 
10 
11 const int maxn = 5011 ; 
12 int n,mx,sum ; 
13 int a[maxn],f[maxn],t[maxn] ; 
14 
15 inline int read() 
16 {
17     char ch = getchar() ; 
18     int x = 0,f = 1 ; 
19     while(ch<'0'||ch>'9') { if(ch=='-') f = -1 ; ch = getchar() ; } 
20     while(ch>='0'&&ch<='9') { x = x*10+ch-48 ; ch = getchar() ; } 
21     return x*f ; 
22 }
23 
24 int main() 
25 {
26     n = read() ; 
27     for(int i=1;i<=n;i++ ) 
28         a[ i ] = read(),f[ i ] = 1 ;  
29     for(int i=1;i<=n;i++) 
30     {
31         for(int j=1;j<i;j++) 
32             if( a[ j ] > a[ i ] ) f[ i ] = max(f[ i ],f[ j ]+1) ; 
33         if( f[ i ]==1 ) t[ i ] = 1 ; 
34         for(int j=1;j<i;j++) 
35             if( f[ j ]+1==f[i]&&a[ j ] > a[ i ] ) 
36                 t[ i ] = t[ i ] + t[ j ] ;    
37             else 
38                 if( f[j]==f[i]&&a[j]==a[i] ) t[ j ] = 0 ; 
39     }
40     for(int i=1;i<=n;i++) 
41         if(f[ i ]>mx) mx = f[ i ] ; 
42     for(int i=1;i<=n;i++) 
43         if(f[i]==mx) sum+=t[i] ; 
44     printf("%d %d
",mx,sum) ;  
45     
46     return 0 ; 
47 }
原文地址:https://www.cnblogs.com/third2333/p/7002015.html