1. 题目概述与解题思路
这道题目源自2024年12月青少年软件编程等级考试C语言四级真题,题目名为"兔子不吃窝边草"。题目描述了一个有趣的场景:若干块草皮排列成一条直线,兔子从指定位置开始吃草,但遵循"不吃相邻草皮"的原则,且只能单向移动(优先向左)。我们需要计算兔子最多能吃多少草。
1.1 问题建模
首先,我们需要将这个问题转化为计算机科学中的经典问题。这实际上是一个变体的"最大不相邻子序列和"问题,在算法领域也被称为"打家劫舍"问题的变种。给定一个数组表示每块草皮上的草量,我们需要找到一个子序列,使得:
- 子序列中的元素不相邻
- 子序列的元素和最大
- 选择策略有特定方向偏好(优先向左)
1.2 输入输出分析
输入格式:
- 第一行:两个整数N和S,表示草皮数量(≤10^5)和起始位置(1≤S≤N)
- 第二行:N个整数,表示每块草皮上的草量
输出格式:
- 一个整数,表示兔子最多能吃掉的草量
示例:
输入:
5 3
2 1 3 5 4
输出:
8
解释:兔子从第3块开始,吃第3块(3),跳过第4块,吃第5块(5),总共3+5=8
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 动态规划解法详解
2.1 基础动态规划思路
对于标准的"最大不相邻子序列和"问题,我们可以使用动态规划来解决。定义dp[i]表示前i个元素中满足条件的最大和,则有状态转移方程:
dp[i] = max(dp[i-1], dp[i-2] + nums[i])
但对于本题,我们需要考虑起始位置和移动方向的限制,这使得问题变得稍微复杂一些。
2.2 本题的特殊处理
由于兔子只能单向移动且优先向左,我们需要分别处理向左和向右两种情况:
- 向左移动:从起始位置S向左到1
- 向右移动:从起始位置S向右到N
然后取两种情况的最大值。但题目说明如果两边结果相同则优先向左,所以需要分别计算。
2.3 具体实现步骤
2.3.1 向左移动的处理
定义left_dp数组,其中left_dp[i]表示从位置i向左能获得的最大草量:
初始化:
left_dp[S] = nums[S]
left_dp[S-1] = nums[S-1] (如果存在)
状态转移:
for i from S-2 downto 1:
left_dp[
