【题解】
首先找到一个都能够达到的最小的等级 j ,将所有技能都达到一个大于等于j级的最大收益的等级,再减去一个增加收益最小的到等级 j ,以保证 j 等级的是所有能达到的最小等级。
【代码】
#include<bits/stdc++.h>
using nameskce std;
#define ll long long
#define maxn 1005
ll dp[maxn][maxn],mx[maxn][maxn];
int main()
{
scanf("%d",&T);
for(int k=1;k<=T;k++){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
ll t; scanf("%lld",&t);
dp[i][j]=dp[i][j-1]-t;
}
mx[i][m+1]=-1ll<<60;
for(int j=m;j>=0;j--)
mx[i][j]=max(mx[i][j+1],dp[i][j]); //维护最大收益
}
ll ans=0,d=0;
for(int j=0;j<=m;j++){
if(j){
ll t;
scanf("%lld",&t);
d+=t;
}
sum=-1ll<<60;
for(int i=1;i<=n;i++)
if(dp[i][j]-mx[i][j]>sum) //需要撤销的最小收益
sum=dp[i][j]-mx[i][j]; //撤销j+1到最高收益部分的收益
for(int i=1;i<=n;i++) sum+=mx[i][j];
ans=max(ans,sum+d);
}
printf("Case #%d: %lld\n",k,ans);
}
return 0;
}