最長下降子序列 + 最長的方案數
阿新 • • 發佈:2019-02-15
連結:http://exam.upc.edu.cn/problem.php?id=1824
題意:求最長下降子序列的長度,和該長度的最長下降子序列有多少個
思路:o(n^2)求最長下降子序列,統計個數時兩個狀態轉移方程一是統計個數的通用方程:if(a[i] < a[j] && dp[i] == dp[j + 1])cnt[i] += cnt[j]
另一個是如果當前點和之前的點是相等的,且dp[i] == dp[j]那麼當前點的所有情況中一定是包括了之前點的方案數,大於等於之前的點。固清空之前點的情況,保留當前點的結果
程式碼:
題意:求最長下降子序列的長度,和該長度的最長下降子序列有多少個
思路:o(n^2)求最長下降子序列,統計個數時兩個狀態轉移方程一是統計個數的通用方程:if(a[i] < a[j] && dp[i] == dp[j + 1])cnt[i] += cnt[j]
另一個是如果當前點和之前的點是相等的,且dp[i] == dp[j]那麼當前點的所有情況中一定是包括了之前點的方案數,大於等於之前的點。固清空之前點的情況,保留當前點的結果
程式碼:
#include <iostream> #include <cstdio> #include <cstring> #include <sstream> #include <string> #include <algorithm> #include <list> #include <map> #include <vector> #include <queue> #include <stack> #include <cmath> #include <cstdlib> using namespace std; map<int,int>mapp; int a[5005]; int dp[5005]; int cnt[5005]; int main() { //freopen("in.txt","r",stdin); int n; scanf("%d",&n); for(int i = 0; i < n; i ++) { scanf("%d",&a[i]); } for(int i = 0; i <n; i ++) { dp[i] = 1; for(int j = 0; j < i; j ++) { if(a[j] >a[i]) { dp[i] = max(dp[i],dp[j] + 1); } } if(dp[i] == 1) cnt[i] = 1; } int maxn = 0; for(int i = 0; i < n; i ++) { maxn = max(maxn,dp[i]); } printf("%d ",maxn); for(int i = 0; i < n; i ++) { for(int j = 0; j < i ; j ++) { if(a[j] > a[i] && dp[i] == dp[j] + 1) { cnt[i] += cnt[j]; } if(a[j] == a[i] &&dp[i] == dp[j]) { cnt[j] = 0; } } } int ans = 0; for(int i = 0; i < n; i ++) { if(dp[i] == maxn) ans += cnt[i]; } printf("%d\n",ans); return 0; }