P2392 kkksc03考前临时抱佛脚——暴力枚举/动态规划

题目背景

kkksc03 的大学生活非常的颓废,平时根本不学习。但是,临近期末考试,他必须要开始抱佛脚,以求不挂科。

题目描述

这次期末考试,kkksc03 需要考 4 科。因此要开始刷习题集,每科都有一个习题集,分别有 s1,s2,s3,s4 道题目,完成每道题目需要一些时间,可能不等(A1,A2,,As1B1,B2,,Bs2C1,C2,,Cs3D1,D2,,Ds4)。

kkksc03 有一个能力,他的左右两个大脑可以同时计算 2 道不同的题目,但是仅限于同一科。因此,kkksc03 必须一科一科的复习。

由于 kkksc03 还急着去处理洛谷的 bug,因此他希望尽快把事情做完,所以他希望知道能够完成复习的最短时间。

输入格式

本题包含 5 行数据:第 1 行,为四个正整数 s1,s2,s3,s4

2 行,为 A1,A2,,As1s1 个数,表示第一科习题集每道题目所消耗的时间。

3 行,为 B1,B2,,Bs2s2 个数。

4 行,为 C1,C2,,Cs3s3 个数。

5 行,为 D1,D2,,Ds4s4 个数,意思均同上。

输出格式

输出一行,为复习完毕最短时间。

输入输出样例 #1

输入 #1

1 2 1 3
5
4 3
6
2 4 3

输出 #1

20

说明/提示

1s1,s2,s3,s420

1A1,A2,,As1,B1,B2,,Bs2,C1,C2,,Cs3,D1,D2,,Ds460

题解

暴力枚举法

暴力枚举法的核心思想是对每科的题目所有可能的分配方式进行枚举,找出左右脑完成该科复习的最短时间。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 计算一科的最短复习时间
int bruteForce(vector<int>& problems) {
int n = problems.size();
int minTime = 1e9;
// 枚举所有可能的分配方式
for (int mask = 0; mask < (1 << n); ++mask) {
int leftTime = 0, rightTime = 0;
for (int i = 0; i < n; ++i) {
if (mask & (1 << i)) {
leftTime += problems[i];
} else {
rightTime += problems[i];
}
}
// 更新最短时间
minTime = min(minTime, max(leftTime, rightTime));
}
return minTime;
}
int main() {
vector<int> s(4);
for (int i = 0; i < 4; ++i) {
cin >> s[i];
}
int totalTime = 0;
for (int i = 0; i < 4; ++i) {
vector<int> problems(s[i]);
for (int j = 0; j < s[i]; ++j) {
cin >> problems[j];
}
// 计算一科的最短复习时间并累加
totalTime += bruteForce(problems);
}
cout << totalTime << endl;
return 0;
}

动态规划法

动态规划法将问题转化为 0 - 1 背包问题,通过状态转移方程找出在背包容量为总时间一半的情况下能装入的最大题目时间总和。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 动态规划计算一科的最短复习时间
int dp(vector<int>& problems) {
int sumTime = 0;
for (int time : problems) {
sumTime += time;
}
int capacity = sumTime / 2;
vector<int> dp(capacity + 1, 0);
for (int time : problems) {
for (int j = capacity; j >= time; --j) {
dp[j] = max(dp[j], dp[j - time] + time);
}
}
return max(dp[capacity], sumTime - dp[capacity]);
}
int main() {
vector<int> s(4);
for (int i = 0; i < 4; ++i) {
cin >> s[i];
}
int totalTime = 0;
for (int i = 0; i < 4; ++i) {
vector<int> problems(s[i]);
for (int j = 0; j < s[i]; ++j) {
cin >> problems[j];
}
// 计算一科的最短复习时间并累加
totalTime += dp(problems);
}
cout << totalTime << endl;
return 0;
}
发布于   xiins  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示