Upgrading Technology

题目链接: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\n", cnt++,ans);
    }
    return 0;
}

 

posted @ 2019-08-03 22:37  ~zcb  阅读(211)  评论(0编辑  收藏  举报