標籤:style blog http color io os ar for sp
轉自http://blog.csdn.net/zhang360896270/article/details/6701589
這題要求最長下降子序列的長度和個數,我們可以增加數組maxlen[size](記錄當前第1個點到第i個點之間的最長下降序列長度)和maxnum[size](記錄1~i之間的最長下降序列個數 ),首先對於最長下降序列屬於DP基礎題,只要對每一個a[i]求出符合要求(a[i] < a[j])的max( maxlen[j] + 1)即可,主要痛點在第二步求下降序列總數
在序列中,如果maxlen[j]+1 == maxlen[i]則說明a[i]和a[j]在同一個下降數列中,那麼我們只要將每一種符合要求的狀態maxnum[j]轉移到maxnum[i]中就可以了,有幾個細節需要注意,題目要求序列是嚴格遞減的,那麼對於兩個相同的數我們只能記錄一個合法解,那麼程式必須只記錄兩個相同數之間的狀態,在這裡用反向推算可以簡化編程,只要找到一個等於的就直接跳出迴圈,還要注意,如果從當前的a[i]一直找到相等的a[j]在這之間都沒有可行狀態的話,當maxnum[i]預設值為1要修改為0(避免錯誤計算),為0的當然無需處理。
#include <iostream>#include <string.h>#include <cstdio>using namespace std;const int size = 5100;int maxlen[size];//記錄當前第1個點到第i個點之間的最長下降序列長度int maxnum[size];//記錄1~i之間的最長下降序列個數int main(){ //freopen("in.txt","r",stdin); int a[size]; int n; while (scanf("%d", &n) != EOF){ for (int i = 1; i <= n; i ++){ scanf("%d", &a[i]); maxnum[i] = 0; maxlen[i] = 1; } for (int i = 1 ; i <= n; i ++){ for (int j = 1; j < i; j ++){ if (a[i] < a[j]){ maxlen[i] = max(maxlen[i], maxlen[j]+1); } } } for (int i = 1; i <= n; i ++) if (maxlen[i] == 1)maxnum[i] = 1; for (int i = 1; i <= n; i ++){ for (int j = i-1; j > 0; j --){ if (a[j] > a[i]){ if (maxlen[j]+1 == maxlen[i]){ maxnum[i] += maxnum[j]; } } if (a[j] == a[i]){ if (maxlen[i] == 1)maxnum[i] = 0;//如果搜尋到一個相同的數後仍沒有找到符合要求的序列,則為了避免重複賦值為0 break; } } } int maxx = -1; for (int i = 1; i <= n; i ++){ if (maxlen[i] > maxx) maxx = maxlen[i]; } int ans = 0; for (int i = 1; i <= n; i ++){ if (maxlen[i] == maxx) ans += maxnum[i] ; } printf("%d %d\n", maxx, ans); } return 0;}
【最長下降子序列的長度和個數】 poj 1952