本文分享的必刷题目是从蓝桥云课、洛谷、AcWing等知名刷题平台精心挑选而来,并结合各平台提供的算法标签和难度等级进行了系统分类。题目涵盖了从基础到进阶的多种算法和数据结构,旨在为不同阶段的编程学习者提供一条清晰、平稳的学习提升路径。
欢迎大家订阅我的专栏:算法题解:C++与Python实现!
附上汇总贴:算法竞赛备考冲刺必刷题(C++) | 汇总
【题目来源】
AcWing:300. 任务安排1 - AcWing题库
【题目描述】
有 N N N 个任务排成一个序列在一台机器上等待执行,它们的顺序不得改变。
机器会把这 N N N 个任务分成若干批,每一批包含连续的若干个任务。
从时刻 0 0 0 开始,任务被分批加工,执行第 i i i 个任务所需的时间是 T i T_i Ti。
另外,在每批任务开始前,机器需要 S S S 的启动时间,故执行一批任务所需的时间是启动时间 S S S 加上每个任务所需时间之和。
一个任务执行后,将在机器中稍作等待,直至该批任务全部执行完毕。
也就是说,同一批任务将在同一时刻完成。
每个任务的费用是它的完成时刻乘以一个费用系数 C i C_i Ci。
请为机器规划一个分组方案,使得总费用最小。
【输入】
第一行包含整数 N N N。
第二行包含整数 S S S。
接下来 N N N 行每行有一对整数,分别为 T i T_i Ti 和 C i C_i Ci,表示第 i i i 个任务单独完成所需的时间 T i T_i Ti 及其费用系数 C i C_i Ci。
【输出】
输出一个整数,表示最小总费用。
【输入样例】
5
1
1 3
3 2
4 3
2 3
1 4
【输出样例】
153
【算法标签】
《AcWing 300 任务安排1》 #动态规划# #斜率优化#
【代码详解】
#include <bits/stdc++.h>
using namespace std;
#define int long long // 定义int为long long类型
const int N = 5005; // 定义最大任务数
// 变量定义:
// n: 任务数量
// s: 启动时间
// sumt[N]: 时间前缀和数组
// sumc[N]: 费用前缀和数组
// f[N]: 动态规划数组,f[i]表示完成前i个任务的最小费用
// q[N]: 单调队列辅助数组(虽然本代码未使用队列优化)
int n, s;
int sumt[N], sumc[N];
int f[N];
int q[N];
signed main()
{
// 输入任务数量和启动时间
cin >> n >> s;
// 输入每个任务的时间和费用,并计算前缀和
for (int i = 1; i <= n; i++)
{
int t, c;
cin >> t >> c;
sumt[i] = sumt[i - 1] + t; // 时间前缀和
sumc[i] = sumc[i - 1] + c; // 费用前缀和
}
// 初始化动态规划数组为极大值
memset(f, 0x3f, sizeof f);
f[0] = 0; // 边界条件:0个任务费用为0
// 动态规划求解
for (int i = 1; i <= n; i++)
{
for (int j = 0; j < i; j++)
{
// 状态转移方程:
// 将j+1到i的任务分为一批完成
// 费用 = 前j个任务费用 + 这批任务的完成时间 × 这批任务的费用 + 启动时间 × 剩余任务的总费用
f[i] = min(f[i], f[j] + sumt[i] * (sumc[i] - sumc[j]) + s * (sumc[n] - sumc[j]));
}
}
// 输出完成所有任务的最小费用
cout << f[n] << endl;
return 0;
}
【运行结果】
5
1
1 3
3 2
4 3
2 3
1 4
153