测评会员优惠活动进行中 · 开通 VIP,有效期内测评不限次 VIP 优惠中 · 测评不限次 立即查看

A29402. 兔子不吃窝边草

填空题 较难

题目描述

兔子不吃窝边草

题目描述

有谚语云:“兔子不吃窝边草”。现给定若干块排列成一条线的草皮,假设兔子从任何一块草皮开始吃,但吃完一块后,绝对不吃直接相邻的草皮,则兔子最多可以吃掉多少草?

输入

输入第一行给出两个正整数,即 N (≤ 105) 为草皮的块数、 i (1 ≤ i ≤ N) 为兔子开始吃的第一块草皮的编号。第二行给出 N 个正整数 (≤ 103),以空格分隔,依次表示每块草皮的含草量。

输出

首先在一行中输出这只兔子最多可以吃掉的草量。下一行按兔子吃草的顺序输出每块被吃掉的草皮的编号。同行数字以 1 个空格分隔,行首尾不得有多余空格。 注意:我们必须假设兔子只朝一个方向跳着吃草,否则如果它可以来回跳,就能吃掉所有的草了。如果朝左右两个方向得到的结果一样,则兔子总是喜欢向左边跳;并且如果有多块草皮都可以得到同样的结果,兔子总是选择跳到离自己最近的那块。

样例输入

样例1:

10 4
2 1 4 3 1 1 5 2 3 1

样例2:

10 8
2 1 4 3 1 1 5 2 3 1

样例输出

样例1:

11
4 7 9

样例2:

9
8 6 3 1

参考答案

#include <iostream> #include <vector> #include <algorithm> using namespace std; pair<int, vector<int>> solve_dp(const vector<int>& vals) { int n = vals.size(); if (n == 0) return {0, {}}; vector<int> dp(n, 0); dp[0] = vals[0]; if (n >= 1) { dp[1] = max(vals[0], vals[1]); } for (int j = 2; j < n; ++j) { dp[j] = max(dp[j - 1], dp[j - 2] + vals[j]); } vector<int> selected; int j = n - 1; while (j >= 0) { if (j == 0) { selected.push_back(j); break; } if (dp[j] == dp[j - 1]) { --j; } else { selected.push_back(j); j -= 2; } } reverse(selected.begin(), selected.end()); return {dp.back(), selected}; } int main() { int N, i; cin >> N >> i; vector<int> arr(N); for (int j = 0; j < N; ++j) { cin >> arr[j]; } vector<int> left_pos, left_vals; for (int pos = i - 2; pos >= 1; --pos) { left_pos.push_back(pos); left_vals.push_back(arr[pos - 1]); } auto [left_sum, left_idx] = solve_dp(left_vals); int total_left = arr[i - 1] + left_sum; vector<int> left_path; for (int idx : left_idx) { left_path.push_back(left_pos[idx]); } vector<int> right_pos, right_vals; for (int pos = i + 2; pos <= N; ++pos) { right_pos.push_back(pos); right_vals.push_back(arr[pos - 1]); } auto [right_sum, right_idx] = solve_dp(right_vals); int total_right = arr[i - 1] + right_sum; vector<int> right_path; for (int idx : right_idx) { right_path.push_back(right_pos[idx]); } bool choose_left = false; if (total_left > total_right) { choose_left = true; } else if (total_left == total_right) { choose_left = true; } else { choose_left = false; } vector<int> path; path.push_back(i); if (choose_left) { for (int pos : left_path) { path.push_back(pos); } } else { for (int pos : right_path) { path.push_back(pos); } } cout << (choose_left ? total_left : total_right) << endl; for (size_t k = 0; k < path.size(); ++k) { if (k > 0) cout << " "; cout << path[k]; } cout << endl; return 0; }
上一题 下一题