题解:
这题还是很难的
用一维数组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;
}