【问题标题】:What's a good algorithm for Defense of a Kingdom?什么是王国防御的好算法?
【发布时间】:2011-02-18 08:36:25
【问题描述】:

我试图解决Defense of a Kingdom problem 并想出了一个算法,但它超过了问题的时间限制。

我想知道在时限内解决这个问题的好算法。

问题:

西奥多实施了一款新的策略游戏“王国保卫战”。在 玩家保卫王国的每一关都由一个 矩形网格的单元格。玩家在某些地方建造弩塔 网格的单元格。塔楼保护同一排的所有牢房, 同一列。没有两座塔共享一行或一列。

位置的惩罚是最大的单元格数 不设防的矩形。例如图片上显示的位置 有 12 分。

帮助西奥多编写一个计算给定位置罚分的程序。

输入

输入文件的第一行包含测试用例的数量。

每个测试用例由一行三个整数组成: w — 网格的宽度,h - 网格的高度和 n - 弩的数量 塔 (1 ≤ w, h ≤ 40 000; 0 ≤ n ≤ min(w, h))。

以下 n 行中的每一行都包含两个整数 xi 和 yi — 塔所占据的单元格坐标 (1 ≤ xi ≤ w; 1 ≤ yi ≤ h)。

输出

对于每个测试用例,输出一个整数 - 的数量 没有被塔保护的最大矩形中的单元格。

示例

输入:
1
15 8 3
3 8
11 2
8 6

输出:12

【问题讨论】:

  • 你的算法是什么?
  • @Oli Charlesworth BruteForce :D
  • 这听起来可能很愚蠢,但目标是输出最大的白色区域?您不必找到塔的位置(因为它们是作为参数给出的)?

标签: c++ algorithm


【解决方案1】:

我会这样做:

给定wh作为比赛场地的宽度和高度,塔的坐标为(x1,y1) .. (xN,yN),将坐标分成两个列表x1..xNy1..yN,对这两个坐标进行排序列表。

然后计算空格,例如dx[] = { x1, x2-x1, ..., xN - xN-1, (w + 1) - xN }。对 y 坐标执行相同操作:dy[] = { y1, y2-y1, ..., yN - yN-1, (h + 1) - yN }。将max(dx)-1 乘以max(dy)-1,你应该得到最大的未覆盖矩形。您必须将 delta 值减一,因为较高坐标塔所覆盖的线包含在其中,但并未被覆盖。

【讨论】:

  • 问题中最难计算的部分是……排序! O(n·log(n))。很好的解决方案,我正在考虑相同的算法。
  • 最大的矩形不必有最大的 dx 和 dy。最大的矩形可能很细很长。如果有一个 12x1 的矩形和一个 3x3 的矩形未被覆盖怎么办?然后,您的算法将给出 36 作为答案,而不是 12。正确吗?
  • hmmm 行不通。 max(dx) 和 max(dy) 不一定要组合。你可以有一个 5x1 区域、一个 1x5 区域和一个 4x4 区域......
  • @Gerco 如果某处有一个 12x1 的区域和一个 3x3 的区域,那么在较大坐标的“交点”上将有一个 12x3 的区域。
  • @Jason 如果某处有一个 5x1 区域和一个 4x4 区域,那么在较大坐标的“交点”上将有一个 5x4 区域。
【解决方案2】:

很容易看出,未防御单元的集合是cartesian product 关卡墙壁上未防御的“洞”。因此,首先,您不需要将整个字段存储在内存中 - 仅存储两个塔的坐标序列就足够了。

第二个观察结果是,在最后一个字段中,所有塔都设置好后,最大的未设防矩形等于两个最宽壁孔的笛卡尔积。因此,它的面积等于孔长度的乘积。所以我们真正需要做的是找到两个最宽的壁孔(一个在x 轴上,一个在y 上),并将它们的长度相乘。这就是答案。

最后一点是关于输入的。塔楼可能会以某种方式改组;但我们需要一种方法来导出所有孔的长度。这可以很容易地通过首先对坐标序列进行排序,分别一个和另一个,然后计算 {xi+1-xi} 和 {yi+1−yi} 一次通过。在同一遍中,我们甚至可以找到最大值——将它们相乘,就完成了。

【讨论】:

    【解决方案3】:

    好的,这可能是另一个第一个想法,

    对于每个防守者,至少有 1 个和最多 4 个相邻的白色区域。

    1. a:=0
    2. 对于每个防守者,从 最大的相邻白色区域。从那里搬到 相邻的未覆盖空间 更大的区域,你没有移动 之前在那里。这样做直到没有可能的移动。
    3. 如果没有可能的移动并且当前区域大于a将当前区域存储在 a

    【讨论】:

    • 这行不通。考虑一个反例:[ ][   ][ ][ ][         ]。如果你从第一个区域附近开始,你会在第二个区域陷入局部极值,永远无法达到全局最大值。
    • for each 后卫。我们将搜索最大的区域。这会起作用的。
    【解决方案4】:

    如果您有 9x6 网格。你有 3 座塔。

    首先计算具有 9 个元素的 x 轴的最小间隙。我们有 3 座塔。 9/3 = 3。所以我们每 3 个元素放置一个塔。

    [ ]
    [ ]
    [x]
    [ ]
    [ ]
    [x]
    [ ]
    [ ]
    [x]
    

    这是最大 2 个间隙。我们可以通过将剩余空间 (6) 按塔的数量 (3) 来解决这个问题。 6/3 = 2。

    现在 y 轴也一样。 6个方格。 3个塔。 6/3 = 每 2 个方格 1 个塔:

    [ ][x][ ][x][ ][x]
    

    1 个空间最大间隙 (3/3)。

    您现在有了每个塔的 x 和 y 坐标(索引为 0):

    1,2
    3,5
    5,8
    

    最大的差距是 2x1 = 2。

    [ ][ ][ ][ ][ ][ ]
    [ ][ ][ ][ ][ ][ ]
    [ ][x][ ][ ][ ][ ]
    [ ][ ][ ][ ][ ][ ]
    [ ][ ][ ][ ][ ][ ]
    [ ][ ][ ][x][ ][ ]
    [ ][ ][ ][ ][ ][ ]
    [ ][ ][ ][ ][ ][ ]
    [ ][ ][ ][ ][ ][x]
    

    我 99% 确信您可以为此创建一个通用公式,而无需返回每个城堡的 x、y 对和最大罚球区的循环。

    【讨论】:

      【解决方案5】:

      编辑我确实注意到了这个程序中的一个小错误: - 当我最初提交它时,它只针对单个测试用例完成;然后我回到我的 IDE 以改进算法以适用于多个测试用例。在我开始工作后,我回到这里编辑这篇文章,但我错过了几行关键的行。它们现在已修复,如果想要保留每个测试用例的相关记录及其相应的惩罚值,我还添加了一些其他可以添加到此类的 cmets。 结束编辑

      我将它封装到一个类中。我很确定可能有一种更优雅的方式来做到这一点,但这就是我想出的,使用你的文本文件示例来填充数据结构和返回惩罚的方法。

      pieces.txt

      1
      15 8 3
      3 8
      11 2
      8 6
      

      DefenderBoard.h

      #ifndef DEFENDER_BOARD_H
      #define DEFENDER_BOARD_H
      
      #include <fstream>
      #include <vector>
      #include <algorithm>
      
      struct Coord {
          unsigned x;
          unsigned y;
      
          Coord() : x(0), y(0) {}
          Coord( unsigned xIn, unsigned yIn ) : x( xIn ), y( yIn ) {} 
      }; 
      
      class DefenderBoard {
      private:
          std::string filename;
          unsigned testcase;
          unsigned gridsize_x;
          unsigned gridsize_y;
          unsigned numTowers;
      
          std::vector<unsigned> penalties;    
          std::vector<Coord> cells;
      
      public:
          explicit DefenderBoard( const std::string& filenameIn );
          ~DefenderBoard();
      
          void getPenalties( std::vector<unsigned>& penalties ) const;
      
      private:
          void getDataFromFile();
          void calculatePenalty();    
      };
      
      #endif // DEFENDER_BOARD_H
      

      DefenderBoard.cpp

      #include "DefenderBoard.h"
      
      DefenderBoard::DefenderBoard( const std::string& filenameIn ) :
      filename( filenameIn ),
      gridsize_x( 0 ), gridsize_y( 0 ),
      testcase( 0 ),
      numTowers( 0 ),
      penalty( 0 ) {
          getDataFromFile();
      }
      
      DefenderBoard::~DefenderBoard() {
      }
      
      void DefenderBoard::getPenalties( std::vector<unsigned>& penaltiesOut ) const {
          penaltiesOut = penalties;
      }
      
      void DefenderBoard::getDataFromFile() {
          std::ifstream file;
          file.open( filename );
          if ( !file.is_open() ) {
              // Note: This ExceptionHandler will not work for you.
              // You will need to supply your own error or exception handling.
              std::ostringstream strStream;
              strStream << __FUNCTION__ << " failed to read in file[" << filename << "]";
              throw ExceptionHandler( strStream );
          }
      
          file >> testcase;
      
          // Temps
          Coord towerCoord;
          // t -> testcase | c - tower coords
          for ( unsigned t = 0; t < testcase; ++t ) {
              file >> gridsize_x;
              file >> gridsize_y;
              file >> numTowers;
      
      
              for ( unsigned c = 0; c < numTowers; ++c ) {
                  file >> towerCoord.x;
                  file >> towerCoord.y;
                  cells.push_back( towerCoord );          
              }
              calculatePenalty();
              // After Penalty is calculated this test case along with the penalty value 
              // can be stored into a struct containing both the penalty and a vector of cells
              // which would be done here and then that struct would be stored into another container to this class
      
              // If the above is choosen to be done then this needs to be called here instead of within the calculate function
              // Clear our cells so it can be reused for each test case found in this file. 
              cells.clear();
          }
      
          file.close();
      }
      
      bool compareCoordsX( const struct Coord& a, const struct Coord& b ) {
          return a.x > b.x;
      }
      
      bool compareCoordsY( const struct Coord& a, const struct Coord& b ) {
          return a.y > b.y;
      }    
      
      void DefenderBoard::calculatePenalty() {
          std::vector<unsigned> xValDiff;
          std::vector<unsigned> yValDiff;
          unsigned diff = 0;
      
          // First Sort By Largest X - Then Find The Differences
          std::stable_sort( cells.begin(), cells.end(), compareCoordsX );
          unsigned idx = 0;
          for ( ; idx < cells.size(); ++idx ) {
              // For First Iteration Only
              if ( idx == 0 ) {
                  diff = gridsize_x - cells[idx].x;
                  xValDiff.push_back( diff );
              } else {
                  diff = cells[idx-1].x - cells[idx].x - 1; // Don't Forget to Subract 1
                  xValDiff.push_back( diff );
              }
          }
          // Also push back the last value - 1
          xValDiff.push_back( cells.back().x - 1 );
      
          // Do Same Thing For Y
          std::stable_sort( cells.begin(), cells.end(), compareCoordsY );
          idx = 0;
          diff = 0;
          for ( ; idx < cells.size(); ++idx ) {
              // First Iteration Only
              if ( idx == 0 ) {
                  diff = gridsize_y - cells[idx].y;
                  yValDiff.push_back( diff );
              } else {
                  diff = cells[idx-1].y - cells[idx].y - 1; // Don't Forget to Subtract 1
                  yValDiff.push_back( diff );
              }
          }
          // Also push back the last value - 1
          yValDiff.push_back( cells.back().y - 1 );
      
          unsigned largestX = xValDiff[0];
          unsigned largestY = yValDiff[0];
          idx = 0;
          for ( ; idx < cells.size(); ++idx ) {   
              if ( xValDiff[idx] > largestX ) {
                  largestX = xValDiff[idx];
              }    
              if ( yValDiff[idx] > largestY ) {
                  largestY = yValDiff[idx];
              }
          }
      
          // Calculate Penalty And Store It
          // EDIT - I did update this code after I had originally posted it
          // and when I added the update I did forget to change this commented section
          // penalty = largestX * largestY;
          // It should be like this:
          penalties.push_back( largestX * largestY );
      
          // I did have this line of code here too but I moved it out of this function and into the getDataFromFile() method.
          // cells.clear();           
      }
      

      ma​​in.cpp

      #include <iostream>
      #include "DefenderBoard.h"
      
      int main() {
          std::vector<unsigned> penalties;
          DefenderBoard board( "pieces.txt" );
          board.getPenalties( penalties );    
      
          unsigned idx = 0;
          for ( ; idx < penalties.size(); ++idx ) {
              std::cout << penalties[idx] << " ";
          }
          std::cout << std::endl;
      
          return 0;
      }
      

      输出

      12
      

      第二次运行 - 两个测试用例:

      pieces.txt

      2
      15 8 3
      3 8
      11 2
      8 6
      12 10 4
      2 2
      9 7
      3 9
      8 5  
      

      输出

      12 8

      注意: 没有边界检查来查看文件中的单元格坐标是否大于 MxN 板的大小。因此,如果网格大小是 8x8,并且有一块坐标为 [12,2] 或 [5,9],这些将破坏算法,给您无效的结果。我将把这些错误案例留作练习。

      算法的实现 该算法的思想是先取大小并减去最远的部分。然后你将取它并从中减去下一个最远的部分并减去 1,直到你到达最后一块,然后最后你将取最后一块本身并从中减去 1。这将为您提供一个方向的所有差异。对另一个方向也重复此操作。然后您正在寻找 x 和 y 中的最大尺寸。一旦你有了它们,你需要做的就是计算 x 和 y 方向上最大差异的乘积,这将为你提供最大的开放区域。

      我还注意到代码中存在某种类型的重复,也可以通过向类中添加几个较小的函数来重构它,但是为了显示算法,我认为在这种情况下并不需要它.该算法唯一的双重 for 循环是从文件中读取数据时。实际计算来自坐标对的线性向量。有 3 个遍历向量的单个 for 循环。前两个相同,一次在 x 方向,一次在 y 方向。所以时间取决于输入 N 的大小或长度。这应该是常数时间。最后一个 for 循环仍然是 N,但要查看大小为 N+1 的向量,该向量仍然是常数时间,其中 N 是塔或坐标对的数量。权衡的是,由于本地向量存储 x 和 y 值的差异,因此存在一点内存开销,对于小型和中等数据集,这不应该是一个问题。

      免责声明

      在对我的回答的评论中提到了这一点:

      感谢您的努力,如果这有负面影响,我很抱歉……但我想知道人们何时会将这种类型的“封装”作为 OO 课程的一部分教授到“类”中……这可能是我的非常个人的品味,但是私有成员函数不带参数并返回 void 对我来说有点危险。在阅读代码时,必须跟踪所有可能被修改的成员,就像在编程的黑暗时代那样拥有全局变量一样糟糕。在这种特殊情况下,它们有助于隐藏第二个测试用例同时使用测试用例 1 和 2 中的塔的错误

      是的,代码中存在错误,我已按照上述方法修复了该错误。现在,如果查看此类对象或 OO 方法的整体设计,他们会发现该实现对此类对象的用户或调用者是隐藏的。他在这里发生的事情有一个特定的顺序。

      分步算法

      • 使用用户定义的构造函数声明此类型的对象。
      • 构造函数采用一个字符串作为文件名来读取数据。
      • 文件打开,如果成功则开始读取数据,否则抛出异常。
      • 它找出有多少个测试用例,并为每个测试用例执行以下操作:
        • 检索塔的数量。
        • 获取此测试用例中每个塔的坐标位置。
        • 计算此测试用例的所有塔的罚分。
        • 存储此案例的惩罚值。
        • 对所有测试用例重复此过程。
        • 关闭文件流。
        • 对象构造完成。
      • 现在对象已经完成,剩下的唯一事情就是让用户调用它的公共接口方法来检索惩罚值。

      其他功能 - 这些可以添加 -

      • 根据网格 MxN 大小检查塔坐标的边界。
      • 所有案例的统计数据 - 重复次数、平均值、中位数、众数、标准偏差等。
      • 内置打印方法。
      • 附加容器,用于存储所有塔单元位置以及每个测试用例的相关惩罚值。
      • 更多错误检查。
      • 一些重构和效率改进。

      修正 lisyarus 在 cmets 中提出了一个很好的观点,基于此,这里是非 OO 版本。

      #include <string>
      #include <vector>
      #include <algorithm>
      #include <fstream>
      
      struct TowerCoordinate {
          unsigned x;
          unsigned y;
      
          TowerCoordinate() : x(0), y(0) {}
          TowerCoordinate( unsigned xIn, unsigned yIn ) : x( xIn ), y( yIn ) {} 
      }; 
      
      struct GridSize {
          unsigned width;
          unsigned height;
      
          GridSize() : width( 0 ), height( 0 ) {}
          GridSize( unsigned widthIn, unsigned heightIn ) : width( widthIn ), height( heightIn ) {}
      };
      
      bool compareCoordsX( const struct TowerCoordinate& a, const struct TowerCoordinate& b ) {
          return a.x > b.x;
      }
      
      bool compareCoordsY( const struct TowerCoordinate& a, const struct TowerCoordinate& b ) {
          return a.y > b.y;
      }
      
      // Returns A Single Penalty
      unsigned calculatePenalties( std::vector<TowerCoordinate>& towerLocations, GridSize& gridSize ) {
          std::vector<unsigned> xValDiff, yValDiff;
          unsigned diff = 0;
          unsigned idx  = 0;
          // First Sort By Largest X - Then Find All Differences
          std::stable_sort( towerLocations.begin(), towerLocations.end(), compareCoordsX );
          for ( ; idx < towerLocations.size(); ++idx ) {
              if ( idx == 0 ) {
                  diff = gridSize.width - towerLocations[idx].x;
                  xValDiff.push_back( diff );
              } else {
                  diff = towerLocations[idx-1].x - towerLocations[idx].x - 1; // Don't Forget To Subtract 1
                  xValDiff.push_back( diff );
              }
          }
          // Also Push Back (Last Value - 1)
          xValDiff.push_back( towerLocations.back().x - 1 );
      
          // Sort By Largest Y - Then Find All Differences
          // First Sort By Largest X - Then Find All Differences
          idx = 0;
          diff = 0;
          std::stable_sort( towerLocations.begin(), towerLocations.end(), compareCoordsY );
          for ( ; idx < towerLocations.size(); ++idx ) {
              if ( idx == 0 ) {
                  diff = gridSize.height - towerLocations[idx].y;
                  yValDiff.push_back( diff );
              } else {
                  diff = towerLocations[idx-1].y - towerLocations[idx].y - 1; // Don't Forget To Subtract 1
                  yValDiff.push_back( diff );
              }
          }
          // Also Push Back (Last Value - 1)
          yValDiff.push_back( towerLocations.back().y - 1 );
      
          unsigned largestX = xValDiff[0];
          unsigned largestY = yValDiff[0];
          idx = 0;
          for ( ; idx < towerLocations.size(); ++idx ) {  
              if ( xValDiff[idx] > largestX ) {
                  largestX = xValDiff[idx];
              } 
              if ( yValDiff[idx] > largestY ) {
                  largestY = yValDiff[idx];
              } 
          }    
          return (largestX * largestY);    
      }
      
      // Returns The Results Of All The Penalties For Each Case
      std::vector<unsigned> getDefenderDataFromFile( const std::string& filename, unsigned& numTestCases, GridSize& gridSize, unsigned& numTowers, std::vector<TowerCoordinate>& towerLocations ) {
          std::ifstream file;
          file.open( filename );
          if ( !file.is_open() ) {
              // This ExceptionHandler will not work for you; you will need to supply your own error or exception handling.
              std::ostringstream strStream;
              strStream << __FUNCTION__ << " failed to read in file[" << filename << "]";
              throw ExceptionHandler( strStream );
          }
      
          file >> numTestCases;
      
          TowerCoordinate towerCoord;
          std::vector<unsigned> penalties;
      
          for ( unsigned t = 0; t < numTestCases; ++t ) {
              file >> gridSize.width;
              file >> gridSize.height;
              file >> numTowers;
      
              for ( unsigned c = 0; c < numTowers; ++c ) {
                  file >> towerCoord.x;
                  file >> towerCoord.y;
                  towerLocations.push_back( towerCoord );
              }
      
              unsigned currentPenalty = calculatePenalties( towerLocations, gridSize );       
              penalties.push_back( currentPenalty );
              towerLocations.clear();         
          }
          file.close();    
          return penalties;
      }
      
      int main() {
          unsigned numTestCases = 0;
          unsigned numTowers    = 0;
          GridSize gridSize;
          std::vector<TowerCoordinate> towerLocations;
          std::vector<unsigned> penalties;
      
          penalties = getDefenderDataFromFile( "pieces.txt", numTestCases, gridSize, numTowers, towerLocations );
      
          unsigned idx = 0;
          for ( ; idx < penalties.size(); ++idx ) {
              std::cout << penalties[idx] << " ";
          }
          std::cout << std::endl;
      
          return 0;
      }
      

      对于这个算法的当前实现,唯一需要注意的是,在每个测试用例之后都会清除塔位置的向量,所以一旦你得到所有惩罚的最终结果,塔的容器就在当前坐标堆栈帧将仅包含最后一组位置,并且不会包含它们的任何先前迭代。再一次,没有根据网格大小对塔坐标进行边界检查。

      【讨论】:

      • 感谢您的努力,如果这会带来负面影响,我很抱歉......但我想知道人们何时会将这种类型的“封装”作为 OO 课程的一部分教授到“类”中...... . 这可能是我个人的喜好,但是不带参数的私有成员函数并返回 void 对我来说是一个危险信号。在阅读代码时,必须跟踪所有可能被修改的成员,就像在编程的黑暗时代那样拥有全局变量一样糟糕。在这种特殊情况下,它们有助于隐藏第二个测试用例同时使用测试用例 1 和 2 的塔的错误。
      • @Timbo 我明白你在说什么,隐藏错误是有道理的。您应该考虑到,我所学到的所有关于编程的知识都是 100% 自学的,没有任何关于编程、计算机科学、软件开发和工程的正式课程。我只是花时间真正实现了挑战本身,并享受实现算法让其他人看到。这里的想法是,一旦算法没有错误,实现对用户隐藏,他们所需要的只是公共方法的结果......
      • @Timbo (...continued) 这里对象接受一个字符串 - 文件名,然后打开该文件进行读取,填充内部隐藏变量并在构建对象时进行所有计算。如果一切顺利,它构建成功后唯一要做的就是调用公共接口方法来检索结果。以这种方式,如果这种类型的类对象是更大的库或 API 的一部分,那么所有的后续工作都被封装隐藏了,用户不必或不必担心他们应该知道的所有定义是声明。
      • @Timbo 如果您仔细观察,没有任何内部变量被修改,它们仅作为引用存储,所有计算都是使用私有方法本地堆栈变量完成的。当有多个测试用例时,唯一的修改恰好是存储单元格的向量。该容器一次用于存储单个测试用例,在计算完成并将结果保存到另一个容器中后,单元的内部容器被清除并准备好在下一次迭代中重用。仅对内部值进行比较。
      • @Timbo 如果需要保留每个测试用例场景,那么需要做的就是添加一个内部结构,该结构具有一个无符号的惩罚值和一个单元格向量作为其成员和然后将该结构的向量作为类本身的内部成员变量,并在执行计算后的下一次迭代之前,在外部循环结束时从文件中读取数据的部分中,然后可以添加该向量将单元格及其惩罚值放入一个临时结构中,并将其推回类成员中。
      【解决方案6】:

      它是一种棋和车问题的变体。

      想想y轴坐标的最大相邻间隙,maxY_by_adjacent

      想想X轴坐标的最大相邻间隙,maxX_by_adjacent

      为了找到相邻的间隙,首先将它们排序。

      这将生成最长的未设防矩形width=maxX_by_adjacent &amp; height=maxY_by_adjacent。 现在,找出这个矩形maxX_by_adjacent * maxY_by_adjacent上的单元格数。

      int h,w,n;
      scanf("%d %d %d",&w,&h,&n);
      int x[n+2];
      int y[n+2];
      for(int i=1;i<=n;i++)
      {
          scanf("%d%d",&x[i],&y[i]);
      }
      x[0] = 0;
      x[n+1] = w + 1;
      y[0] = 0;
      y[n+1] = h + 1;
      sort(x,x+n+1);
      sort(y,y+n+1);
      int maxX_by_adjacent=0;
      int maxY_by_adjacent=0;
      for(int i=1;i<=n+1;i++)
      {
          maxX_by_adjacent=max(maxX_by_adjacent,x[i]-x[i-1]-1);
      }
      for(int i=1;i<=n+1;i++)
      {
          maxY_by_adjacent=max(maxY_by_adjacent,y[i]-y[i-1]-1);
      }
      int ans=maxX_by_adjacent*maxY_by_adjacent;
      printf("%d\n",ans);
      

      【讨论】:

        【解决方案7】:

        你可以使用贪心的方法来解决这个问题。我们的目标是找到最大的不设防矩形。矩形面积=行数*列数。我们必须最大化这两个参数。要找到最大的列数矩形,对墙壁的 x 坐标进行排序,并取两个连续 x 坐标之间的差。这个差的最大值将是我们最终矩形中的最大列数。做同样的事情来查找最终矩形中的行数。参考我的代码。https://github.com/sahazeer123/SPOJ/blob/master/DEFKING.cpp

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-03-17
          • 2022-10-07
          • 2013-06-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-10-06
          • 1970-01-01
          相关资源
          最近更新 更多