for (int iCase = 1; iCase <= T; ++iCase) { int N, B; cin >> N >> B; for (int i = 0; i < N; ++i) { cin >> A[i]; } sort(A.begin(), A.begin() + N); int ans = 0; int index = 0; while (index < N && B >= A[index]) { B -= A[index]; ++ans; ++index; } cout << "Case #" << iCase << ": " << ans <<endl; }
return0; }
因为贪心的时候忘记检查index < n了,导致一次WA罚时。
Plates
动态规划。
状态转移方程:
第i个stack,取走j个盘子,得到的最大Beaty value和。 dp[i][j] = max{dp[i-1][x] + top_sum[j - x] for x in [0, j]}。
for (int iCase = 1; iCase <= T; ++iCase) { int N, K, P; cin >> N >> K >> P; fill(dp.begin(), dp.end(), 0); for (int i = 0; i < N; ++i) { for (int j = 0; j < K; ++j) { cin >> line[j]; if (j > 0) line[j] += line[j - 1]; } for (int j = P; j > 0; --j) { int max_dp = dp[j]; for (int x = j - 1; x >= 0 && j - x - 1 < K; --x) { max_dp = max(max_dp, dp[x] + line[j - x - 1]); } dp[j] = max_dp; // cout << dp[j] << ", "; } // cout << endl; } cout << "Case #" << iCase << ": " << dp[P] <<endl; }
return0; }
Workout
对于K == 1的情况,可以直接采用贪心的策略,将最大的间隔等分。
对于K > 1的情况,可以采取将最优化问题转成判定问题的思路解决。
最优化问题为:求最小的difficulty。
判定问题为:difficulty == x可否实现, 时间复杂度为O(N * K)。
然后判定问题的解的分布为: ... F F F T T T ...,我们要找到第一个T。
采用二分法,搜索区间为[1, max(M_i) = 1^9], 时间复杂度为O(log 1e9)。
故,总的有:
时间复杂度: O(N * K * log 1e9),
空间复杂度: O(N).