信息学奥赛一本通1286:怪盗基德的滑翔翼 题解 动态规划
题目链接:http://ybt.ssoier.cn:8088/problem_show.php?pid=1286
解题思路:
- 选择一个点,往左降落,从左往右看,就是 最长上升子序列;
- 选择一个点,往右降落,从左往右看,就是 最长下降子序列。
所以这道题的答案,就是最长上升子序列和最长下降子序列的长度的较大值。
在下面的程序中,我用 \(f[i]\) 表示以 \(a[i]\) 结尾的最长上升子序列的长度,用 \(g[i]\) 表示以 \(a[i]\) 结尾的最长下降子序列的长度,用 \(ans\) 表示最终的答案。
示例程序:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 202;
int K, n, a[maxn], f[maxn], g[maxn], ans;
int main()
{
scanf("%d", &K);
while (K --)
{
scanf("%d", &n);
ans = 0; // 因为有多组数据,所以每组数据开始前ans都要初始化
for (int i = 1; i <= n; i ++)
scanf("%d", a+i);
for (int i = 1; i <= n; i ++)
{
f[i] = g[i] = 1; // 初始化f[i]和g[i]
for (int j = 1; j < i; j ++)
{
if (a[j] < a[i])
f[i] = max(f[i], f[j]+1);
if (a[j] > a[i])
g[i] = max(g[i], g[j]+1);
}
ans = max(ans, f[i]);
ans = max(ans, g[i]);
}
printf("%d\n", ans);
}
return 0;
}