题目链接:https://ac.nowcoder.com/acm/contest/886/J
题意:你有n个技能,每个技能的初始等级为0级,最高可以升到m级,第i个技能从j-1级升到j级需要花费a[i][j],
当你所有技能都>=k级时(1<=k<=m)你将会获得b[k],由于a[i][j]和b[k]都可能小于0,所以可能存在盈利
的可能,你可以选择任意技能升到某一等级,问你的最高盈利是多少,当然你可以选择都不升级,那样、
你的盈利为0.
思路: 处理每一个等级所花费的前缀和a,将前缀和从后至前依次更新最小值b,处理所有技能都达到某一等级的前
缀和c,枚举所有技能都达到最高的等级,只要一个技能刚好等于这一等级,其他的技能则可以>=该等级,
那么盈利为 c-(某一个刚好等于该等级的花费a+其他>=该等级的花费b),可知应该选取a与b差值最小的技能
等于该等级
#include <bits/stdc++.h> #define ll long long using namespace std; const int N = 1e3 + 10; ll a[N][N],b[N],c[N][N]; int main() { int T,n,m,cnt = 1; for (scanf("%d",&T);T--;) { ll ans = 0; scanf("%d%d",&n,&m); memset(a,0,sizeof(a)); for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { scanf("%lld",&a[i][j]); a[i][j] += a[i][j-1]; c[i][j] = a[i][j]; } a[n+1][m] += a[i][m]; for (int j = m-1; j >= 0; j--) { a[i][j] = min(a[i][j],a[i][j+1]); a[n+1][j] += a[i][j]; } } for (int i = 1; i <= m; i++) { scanf("%lld",&b[i]); b[i]+=b[i-1]; ll mi=99999999999999999; int p=0; for(int j=1;j<=n;j++) { if(c[j][i]-a[j][i]<mi) { mi=c[j][i]-a[j][i]; p=j; } } ans = max(b[i]-a[n+1][i]+a[p][i]-c[p][i],ans); } ll mi=-99999999999999; for(int i=1;i<=n;i++) { if(a[i][0]>mi) { mi=a[i][0]; } } ans = max(ans,mi-a[n+1][0]); printf("Case #%d: %lld ", cnt++,ans); } return 0; }