題意:有i個技能,每次升級都有花費cij,然後所有技能都達到j級送dj塊錢,問你最多能賺多少
解:先將花費乘-1轉換爲收益,對 a[i][j] 維護後綴和,表示 j+1~m 最大收益。
然後 j 從1 到 m 遍歷,j 表示當前某個技能的最低等級,找到 第 i 個技能 最小的後綴和,減去這個後綴和並加上其他技能的後綴和,再加上所以技能都達到 j 的收益取最大值。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
ll sum[1005][1005];
int d[1005];
int a[1005][1005];
int main() {
int cnt=1,t,n,m;
scanf("%d",&t);
while(t--) {
scanf("%d %d",&n,&m);
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++)scanf("%d",&a[i][j]),a[i][j]=-a[i][j];
for(int i=1; i<=m; i++)scanf("%d",&d[i]);
for(int i=1;i<=n;i++){
sum[i][m] = 0;
for(int j=m-1;j>=0;j--){
sum[i][j] = max(0ll,sum[i][j+1]+a[i][j+1]);
}
}
ll now = 0,ans = 0;
for(int j=0;j<=m;j++){
for(int i=1;i<=n;i++)now+=a[i][j];
now+=d[j];
ll tp = 0,mi = 1e18;
for(int i=1;i<=n;i++)tp+=sum[i][j],mi = min(mi,sum[i][j]);
ans = max(ans,tp-mi+now);
}
printf("Case #%d: %lld\n",cnt++,ans);
}
return 0;
}