題目連接:https://ac.nowcoder.com/acm/contest/886/Jc++
題意:你有n個技能,每一個技能的初始等級爲0級,最高能夠升到m級,第i個技能從j-1級升到j級須要花費a[i][j],spa
當你全部技能都>=k級時(1<=k<=m)你將會得到b[k],因爲a[i][j]和b[k]均可能小於0,因此可能存在盈利code
的可能,你能夠選擇任意技能升到某一等級,問你的最高盈利是多少,固然你能夠選擇都不升級,那樣、blog
你的盈利爲0.get
思路: 處理每個等級所花費的前綴和a,將前綴和從後至前依次更新最小值b,處理全部技能都達到某一等級的前it
綴和c,枚舉全部技能都達到最高的等級,只要一個技能恰好等於這一等級,其餘的技能則能夠>=該等級,class
那麼盈利爲 c-(某一個恰好等於該等級的花費a+其餘>=該等級的花費b),可知應該選取a與b差值最小的技能test
等於該等級di
#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\n", cnt++,ans); } return 0; }