Files
python/TangDou/CSP-J/AcWingTraining/T6/440.cpp
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

53 lines
3.1 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
/*
视频讲解
https://www.bilibili.com/video/BV1iT4y1U7tV/?spm_id_from=333.999.0.0
经验总结:
1、从样例入手,通过简单样例,思考人脑思维是如何一点点解决问题的。
2、在模拟样例的过程中,我们其实也是在秉承 多层循环,分别讨论的思路进行的思考。
3、在模拟样例的过程中,我们会发现有些地方是需要特判的,比如环形在1号与n号的交界处等情况,需要 road-=n
4、本题的题意是在任意时刻,你可以终止上一个机器人,它不用走完p个时长。
同时,下一个工厂也不一定非得是现在机器人停止的位置,可以是任意一个。这样自由度就很大,在代码中起到了降维的作用,否则
你就还需要考虑停止的位置,也就是下一个启动的工厂,是不是一定是前一个最大值的停止位,这样就不是一维的f[N]可以描述的了
最开始,我就是卡在这里,认为题解是错误的。
5、画图+样例梳理是解决问题的关键,先用人脑解决掉测试样例是非常重要的办法,然后再用代码模拟实现,再然后才是优化。
*/
int gold[N][N]; // gold[i][j]:第i条路,第j个时刻,可以获得的金币数量
int cost[N]; // cost[i]:在i个工厂购买机器人的花费
int n, m, p; // n个工厂,m个单位时间,p:机器人行走次数的上限
int f[N]; // f[i]:在前i个时间内,可以获得的最多金币数量
int main() {
cin >> n >> m >> p; // 工厂数量,最长的时长,机器人可以行走的次数上限
for (int i = 1; i <= n; i++) // n个工厂,比如2个工厂,其实有两条路径 ,就是1->2,2->1,工厂数量也就是路径数量
for (int j = 1; j <= m; j++) // m个时长
cin >> gold[i][j]; // 每段路径,在每个单位时间,可以获取到的金币数量
for (int i = 1; i <= n; i++) cin >> cost[i]; // 在每个工厂购买机器人需要花费的金币数量
// !!!!!!注意!!!!!!
// 有效状态初始化为负无穷,不能i=0开始,因为下面的代码中会依赖i=0,i=0时f[i]=0
for (int i = 1; i <= m; i++) f[i] = -1e9;
for (int i = 1; i <= m; i++) { // 枚举每个单位时间
for (int j = 1; j <= n; j++) { // 枚举每个工厂
int tmp = f[i - 1] - cost[j]; // 上一个时间单元的最大值,减去在j这个工厂购买机器人的花费金币数
for (int k = 0; k < p && i + k <= m; k++) {
int road = j + k; // 从j这个工厂开始,走k步(已减1),是哪个道路,比如:从1号工厂,走0步,就是1号道路
int time = i + k; // 到达了哪一时刻
if (road > n) road = road - n; // 环形
tmp += gold[road][time]; // 加上此道路,此时刻捡起来的金币数
f[time] = max(f[time], tmp); // 不断取最大值
}
}
}
// 输出
printf("%d\n", f[m]);
return 0;
}