You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

53 lines
3.1 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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;
}