题目描述
给定$n$栋建筑,每栋建筑有一个高度$h$。
试问从哪一栋建筑向左$/$右向低高度建筑进行滑翔,能够穿过的最多建筑。
题目分析
求从某一个点能够穿过的最多建筑,也就是求最长下降子序列。
于是就要求先正向求一遍最长上升子序列(对于某个点就相当于最长下降子序列),用$ans$来记录答案的在最大值
再反向求一遍最长上升子序列,用$ans$来记录答案的在最大值
答案就是$ans$
闫式DP分析法
- 状态集合:$f[i]$位于第$i$个建筑,前面有多少个建筑高度比它低的方案
- 状态属性:最大值
- 状态计算:$f[i] = max(1, max\{f[1 \sim i - 1]\} + 1)$
$Code$
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 110;
int h[N];
int f[N];
int ans;
int t, n;
int main()
{
cin >> t;
while(t -- )
{
ans = 0;
cin >> n;
for(int i = 1; i <= n; i ++ ) cin >> h[i];
// 正向做LIS
for(int i = 1; i <= n; i ++ )
{
f[i] = 1;
for(int j = 1; j < i; j ++ )
if(h[i] > h[j])
f[i] = max(f[i], f[j] + 1);
ans = max(ans, f[i]);
}
// 反向做LIS
memset(f, 0, sizeof f);
for(int i = n; i >= 1; i -- )
{
f[i] = 1;
for(int j = n; j > i; j -- )
if(h[i] > h[j])
f[i] = max(f[i], f[j] + 1);
ans = max(ans, f[i]);
}
cout << ans << endl;
}
return 0;
}