zoukankan      html  css  js  c++  java
  • Candy糖果盒

    Description

    糖果盒 ( Candy Box ) 
    一个被分为 n*m 个格子的糖果盒,第 i 行第 j 列位置的格子里面有 a [ i ][ j ] 颗糖。 
    本来 tenshi 打算送这盒糖果给某 PPMM 的,但是就在要送出糖果盒的前一天晚上,一只极其可恶的老鼠夜袭糖果盒 
    有部分格子被洗劫并且穿了洞。tenshi 必须尽快从这个糖果盒里面切割出一个矩形糖果盒,新的糖果盒不能有洞 
    并且 tenshi 希望保留在新糖果盒内的糖的总数尽量多。 

    Input

    请帮tenshi设计一个程序 计算一下新糖果盒最多能够保留多少糖果。 

    Output

    第一行有两个整数 n、m。第 i + 1 行的第 j 个数表示 a [ i ][ j ],如果这个数为 0 
    则表示这个位置的格子被洗劫过。其中: 
    1 ≤ n,m ≤ 1000 
    0 ≤ a [ i ][ j ]≤ 255

    Sample Input

    输出最大糖果数

    Sample Output

    3 4
    1  2  3  4
    5  0  6  3
    10 3  4  0

    Hint

    17

    (这题是原题的加强版)

    题目描述

    一个被分为个格子的月饼盒,第行第列位置的格子里面有个月饼。本来CCC老师打算送这盒月饼给某人的,但是就在要送出月饼盒的前一天晚上,一只极其可恶的老鼠夜袭月饼盒,有部分格子被洗劫并且穿了洞。CCC老师必须尽快从这个月饼盒里面切割出一个矩形月饼盒,新的月饼盒不能有洞,并且CCC老师希望保留在新月饼盒内的月饼的总数尽量多。任务:请帮CCC老师设计一个程序 计算一下新月饼盒最多能够保留多少月饼。 如果,则表示这个格子是洞.

    算法分析

       这个题目是: 给你一个矩阵,要求你找一个子矩阵,使得子矩阵内不包含,并且矩阵内元素之和最大.

       首先下一个定义,有效矩形: 内部不包含0元素的矩形. 极大子矩形: 4个边界都不能向外扩展的有效矩形. 由于,因此最大子矩形一定是极大子矩形

    如何能够有效利用极大子矩形的性质成为了问题的关键.

    设表示能够向上扩展的最大长度,也就是说最大可以扩展到它上方的第一个洞的下方,或者一直扩展到最上面的边界. 我们称到的这一条线段为能够向上扩展的最长线段. 枚举以能够向上扩展的最长线段为中心,计算能够向左扩展的最大长度,能够向右扩展的最大长度.

    注意: 这样扩展出来的矩形不一定是极大子矩形,上,左,右3个边界不可以再向外扩展了,但是可能还可以向下扩展. 但是可以证明这样扩展出来的矩形集合是一定包含了极大子矩形的集合的.也就是说,我们求出集合中的所有矩形中元素之和最大的矩形就一定是最大子矩形了.

    这个算法的时间复杂度是O(mn)的,已经达到了理论下界了,至此问题已经得到很好的解决.

      

     var
    
    
        ans,high,right,left,i,j,k,t,s,n,m:longint;
    
    
        sum,a,l,r,h:array[-10..1000,-10..1000] of longint;
    
    
      function min(p,q:longint):longint;
    
    
        begin
    
    
          if p>q then exit(q); exit(p);
    
    
        end;
    
    
      begin
    
    
         readln(n,m);
    
    
         for i:=1 to n do
    
    
           begin
    
    
             for j:=1 to m do
    
    
              begin
    
    
               read(a[i,j]);
    
    
               sum[i,j]:=sum[i,j-1]+sum[i-1,j]-sum[i-1,j-1]+a[i,j];
    
    
              end;
    
    
              readln;
    
    
           end;
    
    
         for i:=1 to n do    //L[i,j]代表(i,j)这个点向左伸展的长度为多少
    
    
            begin
    
    
              for j:=1 to m do
    
    
                  if a[i,j]=0 then
    
    
                     l[i,j]:=0
    
    
                     else  
    
    
                              l[i,j]:=l[i,j-1]+1;
    
    
              for j:=m downto 1 do  //R[i,j]代表(i,j)这个点向右伸展的长度为多少
    
    
                if a[i,j]=0 then
    
    
                   r[i,j]:=0
    
    
                   else r[i,j]:=r[i,j+1]+1;
    
    
           end;
    
    
        for i:=1 to n do      //H[i,j]代表(i,j)这个点向上伸展的长度为多少
    
    
                for j:=1 to m do
    
    
                   if a[i,j]<>0 then
    
    
                     if a[i-1,j]=0 then
    
    
                          h[i,j]:=1
    
    
                       else
    
    
                       begin
    
    
                       h[i,j]:=h[i-1,j]+1;
    
    
                       l[i,j]:=min(l[i-1,j],l[i,j]);//此时L代表以(i,j)为右下角的那个矩形向左伸展的长度
    
    
                       r[i,j]:=min(r[i-1,j],r[i,j]);////此时R代表以(i,j)为右下角的那个矩形向右伸展的长度
    
    
                       end;
    
    
        for i:=1 to  n do
    
    
          for j:=1 to m do
    
    
            begin
    
    
              left:=j-l[i,j]+1;
    
    
              right:=j+r[i,j]-1;
    
    
              high:=i-h[i,j]+1;
    
    
              if ans<sum[i,right]-sum[high-1,right]-sum[i,left-1]+sum[high-1,left-1]  then
    
    
                 ans:=sum[i,right]-sum[high-1,right]-sum[i,left-1]+sum[high-1,left-1] ;
    
    
            end;
    
    
      writeln(ans);
    
    
     end.
    View Code

    我的代码

    var
    sum,l,r,ll,rr,h,a:array[0..1000,0..1000] of longint;
    x,y,z,m,ans,max,i,j,k,n:longint;
    function min(x,y:longint):longint;
     begin
      if x<y then
      exit(x)
      else exit(y);
     end;
     begin
     read(n,m);
     for i:=1 to n do
       for j:=1 to m do
       read(a[i,j]);
       for i:=0 to n do
         for j:=0 to m do
         sum[i,j]:=sum[i-1,j]+sum[i,j-1]-sum[i-1,j-1]+a[i,j];
       for i:=1 to n do
       begin
         for j:=1 to m do
         if a[i,j]<>0 then
         l[i,j]:=l[i,j-1]+1;
         for j:=m downto 1 do
         if a[i,j]<>0 then
         r[i,j]:=r[i,j+1]+1;
         for j:=1 to m do
         if a[i,j]<>0 then
         begin
         h[i,j]:=h[i-1,j]+1;
             if a[i-1,j]=0 then
              begin
                  ll[i,j]:=l[i,j];
                  rr[i,j]:=r[i,j];
              end   else
              begin
                  ll[i,j]:=min(l[i,j],ll[i-1,j]);
                  rr[i,j]:=min(r[i,j],rr[i-1,j]);
             end;
         end;
       end;
      for i:=1 to n do
         for j:=1 to m do
         if a[i,j]<>0 then
         begin
         x:=i-h[i,j]+1;
         y:=j-ll[i,j]+1;
         z:=j+rr[i,j]-1;
         ans:=sum[i,z]+sum[x-1,y-1]-sum[i,y-1]-sum[x-1,z];
         if ans>max then max:=ans;
        end;
         writeln(max);
    end.
    View Code
  • 相关阅读:
    38861cba61c66739c1452c3a71e39852.ttf net::ERR_ABORTED 404 (Not Found)
    php 进制转换base_convert
    mysql find_in_set 函数 使用方法
    xmind 破解
    python 获取 一个正整数的二进制
    算法 求一个数的平方根
    详细的描述一个测试活动完整的过程。
    常见的测试用例设计方法都有哪些?请分别以具体的例子来说明这些方法在测试用例设计工作中的应用。
    HTTP 协议中 Vary 的一些研究
    svn cleanup failed–previous operation has not finished; run cleanup if it was interrupted
  • 原文地址:https://www.cnblogs.com/fhlxpyz/p/6133960.html
Copyright © 2011-2022 走看看