题解:
这题还是很难的
用一维数组f储存第i秒能获得的最大钱数
因为最多同时存在1个机器人
第i秒时第j个机器人走k次(1<=k<=p)
f[i]=max(f[i],f[i-k]-pay[last]+sum)
这里是从当前点倒推
last是上一个点
当last=0,last=n
sum要一遍遍加上钱k秒第last路上的金币数
每次减去第last条道路(即第last个工厂机器人)的价格
如果i-k<0
直接退出k循环,时间不为负
因为结果可能是负的
初始化为-99999999
f[0]=0,即第0秒金币数为0
输出第m秒的值
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 1005;
int n,m,p;
int dp[maxn],gg[maxn][maxn],cost[maxn];
//gg[i][j] 表示 第i个工厂的第j时刻 路上会出现多少金币
int max(int a,int b){return a>b?a:b;}
int main(){
memset(dp,-127,sizeof(dp));
scanf("%d%d%d",&n,&m,&p);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&gg[i][j]);
for(int i=1;i<=n;i++)scanf("%d",&cost[i]);
dp[0]=0;//一定要初始化dp[0]=0哦,不然 ε=(′ο`*)))
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
int begin = j-1;
if(!begin)begin=n;
int sum = gg[begin][i];
for(int k=1;k<=p;k++){
if(i-k<0)break;
dp[i]=max(dp[i],dp[i-k]+sum-cost[begin]);
begin--;
if(!begin)begin=n;
sum+=gg[begin][i-k]; //sum 即 从 begin工厂开始 走了k步之后在一路上的金币收益总和(倒推)
}
}
}
/*
具体意思
在第i 时刻
到达了 第j工厂
从begin工厂出发的
为什么begin=j-1呢,因为k也就是倒推的第一步就是1,也就是走了一步即倒推 当前时刻的上k=1 步
begin到j工厂 赚了begin到j工厂路上的金币
然后就是倒推
因为每个机器人 在开始都给出了只能走多少步
所以,在 i时间时,可以由i-k 时刻的最优解 加上,当前在begin工厂买了机器人 走了k步之后 在路上获得的金币
比如: 工厂 1 2 3 4
在1时刻,走到2工厂,就是从1工厂花1时刻走过来,加上1工厂到2工厂路上的金币,减去在1工厂 买机器人的金币
*/
printf("%d",dp[m]);
return 0;
}