洛谷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\n",mx,sum) ; 45 46 return 0 ; 47 }