蓝桥杯 拦截导弹 (DP入门)

本文介绍了一种求解最长下降子序列问题的算法实现,通过动态规划的方法找到序列中最大的下降子序列长度,并同样解决了寻找最长上升子序列的问题。


思路:求出序列的最长下降子序列即可 ,开一个DP数组,DP[i]表示第i个点的最大下降长度,扫面第i个点前的每一个点。
        第二个问题与第一个类似,也可用贪心完成,故不做概述。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <iomanip>
#include <cmath>
#include <cstring>
#include <vector>
#include <queue>
#include <stdlib.h>
#include <set>
#include <map> 
using namespace std;
vector<int>A,B;
int DP[10005],DPS[10005];
int main()
{
    ios::sync_with_stdio(false);
    int t;
    while(cin>>t)
        A.push_back(t);
        for(int i=0;i<A.size();i++)
        {
            DPS[i]=1;
            DP[i]=1;
        }
        int ans1=0,ans2=0;
    for(int i=0;i<A.size();i++)
    {
        for(int j=0;j<i;j++)
        {
            if(A[j]>A[i])
            {
                DP[i]=max(DP[j]+1,DP[i]);
            }
            if(A[j]<A[i])
            {
                DPS[i]=max(DPS[i],DPS[j]+1);
            }
        }
    }
    for(int i=0;i<A.size();i++)
    {
        ans1=max(ans1,DP[i]);
        ans2=max(ans2,DPS[i]);
    }
    cout<<ans1<<endl;
    cout<<ans2<<endl;
    return 0;
}

### 蓝桥杯动态规划问题概述 动态规划(Dynamic Programming, DP)是一种常用的算法设计技术,适用于具有重叠子问题和最优子结构性质的问题。以下是关于蓝桥杯中常见动态规划问题的解题思路及相关知识点。 #### 动态规划的核心要素 动态规划主要依赖于两个核心特性: 1. **最优子结构**:一个问题的最优解可以通过其子问题的最优解构建而成[^2]。 2. **重叠子问题**:在求解过程中,许多子问题是重复出现的,因此可以缓存这些子问题的结果以提高效率[^3]。 #### 动态规划的一般流程 - 定义状态变量并初始化边界条件。 - 寻找状态转移方程,这是解决问题的关键部分。 - 使用迭代或记忆化递归的方式填充状态表。 - 输出最终结果。 --- ### 示例题目解析 #### 题目描述 假设有一道典型的蓝桥杯动态规划题目如下: > 给定一个长度为 `n` 的整数数组 `arr` 和一个正整数 `k`,找出其中连续子数组的最大和不超过 `k` 的最大可能值。如果不存在这样的子数组,则返回 `-1`。 #### 输入输出要求 - 输入:第一行为测试用例数量 `T`;对于每个测试用例,第一行包含两个整数 `n` 和 `k`,第二行为 `n` 个整数表示数组 `arr`。 - 输出:对于每个测试用例,输出满足条件的最大子数组和。 #### 解题思路 此问题可以用滑动窗口配合前缀和的思想来优化暴力枚举的方法,也可以通过动态规划解决。以下是基于动态规划的状态定义与转移方程: 1. **状态定义** 设 `dp[i][j]` 表示从第 `i` 个元素到第 `j` 个元素构成的子数组的最大和,且该和不超过 `k`。 2. **初始条件** 对于单个元素的情况,即当 `i == j` 时,`dp[i][i] = arr[i]` 如果它小于等于 `k`,否则设为负无穷大。 3. **状态转移方程** 当考虑多个元素组成的子数组时,有以下关系: \[ dp[i][j] = \begin{cases} max(dp[i][j-1], sum(i,j)) &\text{if } sum(i,j) \leq k \\ -\infty &\text{otherwise} \end{cases} \] 4. **时间复杂度分析** 此方法的时间复杂度为 \(O(n^2)\),适合中小规模数据集。若需进一步优化,可引入单调队列或其他技巧降低复杂度至线性级别。 #### Python 实现代码 ```python def max_subarray_sum(arr, n, k): # 初始化前缀和数组 prefix_sum = [0] * (n + 1) for i in range(1, n + 1): prefix_sum[i] = prefix_sum[i - 1] + arr[i - 1] result = -float('inf') deque = [] for j in range(n + 1): while deque and prefix_sum[j] - prefix_sum[deque[0]] > k: deque.pop(0) if deque: current_sum = prefix_sum[j] - prefix_sum[deque[0]] result = max(result, current_sum) while deque and prefix_sum[j] <= prefix_sum[deque[-1]]: deque.pop() deque.append(j) return result if result != -float('inf') else -1 # 测试样例 test_cases = int(input()) for _ in range(test_cases): n, k = map(int, input().split()) arr = list(map(int, input().split())) print(max_subarray_sum(arr, n, k)) ``` 上述代码实现了更高效的解决方案,采用双端队列维护最小前缀和索引来快速更新候选答案。 --- ### 总结 动态规划作为一种强大的工具,在处理涉及最优化、计数等问题时非常有效。针对蓝桥杯中的具体题目,合理选择状态定义方式以及推导清晰的状态转移方程至关重要。此外,还需注意边界情况及性能调优策略的应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值