信息学奥赛一本通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;
}
posted @ 2021-07-18 15:36  quanjun  阅读(415)  评论(0编辑  收藏  举报