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

A25067. 小白兔拔萝卜

填空题 困难

题目描述

小白兔拔萝卜

题目描述

小白兔拔萝卜,但是它的力量有限,太大的萝卜它拔不动。于是它叫来了一群小伙伴……

本题就请你根据小白兔们的力量和拔出这个萝卜需要的力量,告诉小白兔,它最少需要哪些伙伴能拔出这只大萝卜。

输入描述

输入在第一行里给出两个不超过 1000 的正整数 n 和 T,分别是小白兔的数量和拔出这个萝卜需要的力量。

随后一行给出 n 个不超过 100 的正整数,其中第 i 个数对应编号为 i 的小白兔的力量(i=1, … , n)。

输出描述

如果兔子们有可能拔成功,则首先在第一行输出最少需要多少只兔子才能拔出这只萝卜,然后第二行从小到大输出参与拔萝卜的兔子们的编号。编号间以 1 个空格分隔,行首尾不得有多余空格。

如果所有兔子合力都不能拔出萝卜,则首先在第一行输出 0,随后在第二行中输出:Suan4 le ba, hai2 cha4 X. 其中 X 是小白兔们缺少的力量值。

注意:力量等于 T 是可以拔出萝卜的。 解可能不是唯一的,你只要随便输出一组就可以。

样例输入1

10 100
3 25 4 91 13 81 64 38 49 51

样例输出1

2
2 4

样例输入2

5 50
3 2 8 5 10

样例输出2

0
Suan4 le ba, hai2 cha4 22.

参考答案

//答案来源于AI #include <iostream> #include <vector> #include <algorithm> #include <climits> using namespace std; const int INF = 10000; int main() { int n, T; cin >> n >> T; vector<int> powers(n); long long total = 0; for (int i = 0; i < n; i++) { cin >> powers[i]; total += powers[i]; } // 处理总力量不足的情况 if (total < T) { cout << "0" << endl; cout << "Suan4 le ba, hai2 cha4 " << T - total << "." << endl; return 0; } // 动态规划数组,dp[j]表示达到力量j所需的最少兔子数 vector<int> dp(T + 1, INF); // 记录状态转移路径 vector<int> prevState(T + 1, -1); vector<int> lastId(T + 1, -1); // 初始状态:0力量需要0只兔子 dp[0] = 0; // 动态规划过程 for (int i = 0; i < n; i++) { int w = powers[i]; // 倒序遍历,避免重复计算 for (int j = T; j >= 0; j--) { if (dp[j] == INF) continue; // 当前状态不可达 int next = j + w; if (next > T) next = T; // 力量超过T的都视为达到T // 更新新状态的最小兔子数 if (dp[next] > dp[j] + 1) { dp[next] = dp[j] + 1; prevState[next] = j; // 记录前一个状态 lastId[next] = i; // 记录最后加入的兔子索引 } } } // 回溯求解方案 vector<int> selected; int cur = T; while (cur > 0) { selected.push_back(lastId[cur] + 1); // 转换为1-indexed编号 cur = prevState[cur]; } sort(selected.begin(), selected.end()); // 输出结果 cout << dp[T] << endl; for (int i = 0; i < selected.size(); i++) { if (i > 0) cout << " "; cout << selected[i]; } cout << endl; return 0; }
上一题 下一题