1. 程式人生 > 實用技巧 >AcWing 1014. 登山 dp

AcWing 1014. 登山 dp

地址https://www.acwing.com/problem/content/description/1016/

五一到了,ACM隊組織大家去登山觀光,隊員們發現山上一個有N個景點,
並且決定按照順序來瀏覽這些景點,即每次所瀏覽景點的編號都要大於前一個瀏覽景點的編號。 同時隊員們還有另一個登山習慣,就是不連續瀏覽海拔相同的兩個景點,並且一旦開始下山,就不再向上走了。 隊員們希望在滿足上面條件的同時,儘可能多的瀏覽景點,你能幫他們找出最多可能瀏覽的景點數麼? 輸入格式 第一行包含整數N,表示景點數量。 第二行包含N個整數,表示每個景點的海拔。 輸出格式 輸出一個整數,表示最多能瀏覽的景點數。 資料範圍
2≤N≤1000 輸入樣例: 8 186 186 150 200 160 130 197 220 輸出樣例: 4

演算法1
依舊是最長上升子序列
類似 AcWing 482. 合唱隊形
不同的哪題是問總人數要除開多少人 可以保持最長上升子序列隊形
這裡是問 最長上升子序列的人數

// 11235.cpp : 此檔案包含 "main" 函式。程式執行將在此處開始並結束。
//

#include <iostream>
#include <algorithm>



using namespace std;

const int N = 1120;

int arr[N];

int dp[N];
int rdp[N]; int n; void solve() { for (int i = 0; i < n; i++) { dp[i] = 1; rdp[i] = 1; } for (int i = 1; i < n; i++) { for (int j = 0; j < i; j++) { if (arr[i] > arr[j]) { dp[i] = max(dp[i], dp[j] + 1); } } }
for (int i = n - 2; i >= 0; i--) { for (int j = i + 1; j < n; j++) { if (arr[i] > arr[j]) { rdp[i] = max(rdp[i], rdp[j] + 1); } } } int ans = 0; for (int i = 0; i < n; i++) { int sum = dp[i] + rdp[i] - 1; //除開自己 向兩邊的由高到低佇列長度 ans = max(ans, sum); } cout << ans << endl; return; } int main() { cin >> n; for (int i = 0; i < n; i++) { cin >> arr[i]; } solve(); return 0; }