zoukankan      html  css  js  c++  java
  • 2019牛客暑期多校训练营(第六场)J Upgrading Technology(矩阵前缀和+最小子串和+贪心)

    题目链接:https://ac.nowcoder.com/acm/contest/886/J

    题目大意:

      有n个种类的树,每个种类对应m个级别。每个种类升级都需要一定的成本,且当n个种类的等级都达到一个等级时,将获得这个等级的利润,问能获得的最大金额。

    解题报告:

      学到了新的东西:最小子串和,可以记录从i点开始往后的最小自串和。

      题解都在代码里,根据当前的矩阵前缀和,和找n-1条子串的最小子串和(因为是成本所以要最小,至多n-1条边,否则就构成矩阵了,没必要重复判断)。

    AC代码:

     1 #include<bits/stdc++.h>
     2 #define numm ch-48
     3 #define pd putchar(' ')
     4 #define pn putchar('
    ')
     5 #define pb push_back
     6 #define fi first
     7 #define se second
     8 #define fre1 freopen("1.txt","r",stdin)
     9 #define fre2 freopen("2.txt","w",stdout)
    10 using namespace std;
    11 template <typename T>
    12 void read(T &res) {
    13     bool flag=false;char ch;
    14     while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true);
    15     for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm);
    16     flag&&(res=-res);
    17 }
    18 template <typename T>
    19 void write(T x) {
    20     if(x<0) putchar('-'),x=-x;
    21     if(x>9) write(x/10);
    22     putchar(x%10+'0');
    23 }
    24 
    25 typedef long long ll;
    26 const int maxn=1010;
    27 const int N=60;
    28 const int inf=0x3f3f3f3f;
    29 const ll INF=0x3f3f3f3f3f3f3f3f;
    30 const int mod=998244353;
    31 
    32 ll mp[maxn][maxn];  ///每行每列的元素
    33 ll d[maxn];         ///每列的利润
    34 ll wtz[maxn];       ///记录从1到i列的矩阵前缀和
    35 ll dp[maxn][maxn];  ///记录最小子串和
    36 ll ls[maxn];        ///利润前缀和
    37 int main()
    38 {
    39     int _,k=0,n,m;
    40     read(_);
    41     while(_--) {
    42         read(n),read(m);
    43         for(int i=1;i<=n;i++)
    44             wtz[i]=0;
    45         for(int i=1;i<=n;i++)
    46             for(int j=1;j<=m;j++) {
    47                 read(mp[i][j]);
    48                 wtz[j]+=mp[i][j];
    49             }
    50         for(int i=1;i<=m;i++)       ///从1到i列的矩阵前缀和
    51             wtz[i]+=wtz[i-1];
    52         for(int i=1;i<=n;i++) {         ///记录最小子串和
    53             dp[i][m+1]=0;
    54             for(int j=m;j>=1;j--)
    55                 dp[i][j]=min(dp[i][j+1]+mp[i][j],mp[i][j]);
    56         }
    57         for(int i=1;i<=n;i++)
    58             for(int j=1;j<=m;j++)
    59                 if(dp[i][j]>0)
    60                     dp[i][j]=0;
    61         for(int i=1;i<=m;i++) {
    62             read(d[i]);
    63             ls[i]=ls[i-1]+d[i];
    64         }
    65         ll res=0;
    66         for(int i=1;i<=m;i++) {
    67             ll sum=0,del=-INF;
    68             for(int j=1;j<=n;j++) {
    69                 del=max(dp[j][i],del);       ///要减掉的那一行
    70                 sum+=dp[j][i];
    71             }
    72             res=max(ls[i-1]-(sum-del)-wtz[i-1],res);    ///利润-子串和(至多n-1个)+矩阵前缀和
    73         }
    74         res=max(ls[m]-wtz[m],res);
    75         printf("Case #%d: ",++k);
    76         write(res);pn;
    77     }
    78     return 0;
    79 }
    代码在这里!
  • 相关阅读:
    C++ 模板实现约瑟夫环
    C++实现向文件输出对象并读取对象
    C++实现对本地文件加行号并输出到本地文件
    C++ vector动态容量变化
    C++纯虚函数应用实例
    华为2016研发工程师-删数字
    iOS-宫格拼图
    iOS-审核4.3入坑(已出坑)
    Mac-关闭Mac电脑启动声音(咚~)
    彻底完全卸载SQL Server 2005教程
  • 原文地址:https://www.cnblogs.com/wuliking/p/11296573.html
Copyright © 2011-2022 走看看