当前位置:   article > 正文

题解 # 二维矩阵最大矩形问题#_小明有一张n*m的方格纸,且部分小方格中涂了颜色,部分小方格还是空白。给出n(2

小明有一张n*m的方格纸,且部分小方格中涂了颜色,部分小方格还是空白。给出n(2

题目:

小明有一张N*M的方格纸,且部分小方格中涂了颜色,部分小方格还是空白。


给出N (2<Ns30)和M(2sMs30)的值,及每个小方格的状态((被涂了颜色小方格用数字1表示,空白小方格用数字0表示);

请帮助小明找出最大的矩形空白区域,并输出该矩形空白区域由多少个小方格组成。


例如:N=4, M=5,4*5的方格纸中每个小方格的状态如下图:

 

最大的空日区域由6个小方格组成(红色框区域)。

思路:

暴力穷举法

1、将每一个方格的下边0的个数、右边0的个数进行统计

2、在由下边0的个数和右边0的个数以及该方格围城的矩形中,筛选出值是1的方格,进行0个数的回退。

3、将每一个方格的下标、下边0的个数,右边0的个数进行保存,最后再求最大的面积

4、如果这个方格里面是1则,从该方格出发是不能构成数据全部为0的矩形的,行刺可以直接将该方格的下边0和右边0的个数设置为0,排除即可。

5、最后查找 下边0的个数 >= 1   同时   右边0的个数也 >= 1的找到面积最大的矩形。

代码:

  1. #include<stdio.h>
  2. #define N 4
  3. #define M 5
  4. #define NUM (N*M)
  5. int main()
  6. {
  7. int arr[N][M] = {
  8. {1,1,0,0,0},
  9. {1,0,1,0,0},
  10. {0,0,0,1,1},
  11. {0,0,0,1,0},
  12. };
  13. // 本例采用数组存储,因为有多个数组因此采用 二维数组方式
  14. int posArr[NUM][4]={0};
  15. // 先获取每一个数据
  16. // arr数据的行下标
  17. int i;
  18. // arr数据的列下标
  19. int j;
  20. printf("原始数组信息:\n");
  21. for(i=0;i<N;i++)
  22. {
  23. for(j=0;j<M;j++)
  24. {
  25. printf("%d ",arr[i][j]);
  26. }
  27. printf("\n");
  28. }
  29. // 查找下边0的临时下标
  30. int k;
  31. // 查找右边0的临时下标
  32. int t;
  33. // 下边0的个数
  34. int bottom = 0;
  35. // 右边0的个数
  36. int right = 0;
  37. // 存放最大矩形信息的下标。
  38. int maxI;
  39. // 最大矩形的面积
  40. int maxArea;
  41. for(i=0;i<N;i++)
  42. {
  43. for(j=0;j<M;j++)
  44. {
  45. // 如果该数据是1,不能构成以这个点为定点的矩形,则不需要向下和向右统计0的个数了
  46. if(arr[i][j] != 0)
  47. {
  48. posArr[i*M+j][0] = i;
  49. posArr[i*M+j][1] = j;
  50. posArr[i*M+j][2] = 0;
  51. posArr[i*M+j][3] = 0;
  52. continue;
  53. }
  54. // 如果该数据是0,可能构成 以这个点为定点的矩形
  55. bottom = 0;
  56. right = 0;
  57. // 查找下边0的个数;
  58. for(k=j+1;k<M;k++)
  59. {
  60. if(arr[i][k] == 0)
  61. {
  62. right++;
  63. }
  64. else
  65. {
  66. break;
  67. }
  68. }
  69. // 向右查找0的个数
  70. for(t=i+1;t<N;t++)
  71. {
  72. if(arr[t][j] == 0)
  73. {
  74. bottom++;
  75. }
  76. else
  77. {
  78. break;
  79. }
  80. }
  81. // 以行为准查找1,将不和要求的矩形排除掉,当前位置为i 和 j
  82. for(k=i+1;k<=i + bottom;k++)
  83. {
  84. for(t=j;t<=j + right;t++)
  85. {
  86. if(arr[k][t] == 1)
  87. {
  88. if(k > t)
  89. {
  90. bottom -= 1;
  91. }
  92. else if(k < t)
  93. {
  94. right -= 1;
  95. }
  96. else
  97. {
  98. bottom -= 1;
  99. right -= 1;
  100. }
  101. }
  102. }
  103. }
  104. posArr[i*M+j][0] = i;
  105. posArr[i*M+j][1] = j;
  106. posArr[i*M+j][2] = bottom;
  107. posArr[i*M+j][3] = right;
  108. }
  109. }
  110. // 访问数据
  111. maxI = 0;
  112. maxArea=0;
  113. int tempArea = 0;
  114. for(i=0;i<NUM;i++)
  115. {
  116. if(posArr[i][2] == 0 && posArr[i][3] != 0)
  117. {
  118. tempArea = 1 * posArr[i][3];
  119. }
  120. if(posArr[i][2] != 0 && posArr[i][3] == 0)
  121. {
  122. tempArea = 1 * posArr[i][2];
  123. }
  124. if(posArr[i][2] == 0 && posArr[i][3] == 0)
  125. {
  126. tempArea = 1;
  127. }
  128. if(posArr[i][2] != 0 && posArr[i][3] != 0)
  129. {
  130. tempArea = (posArr[i][2]+1) * (posArr[i][3]+1);
  131. }
  132. if(maxArea < tempArea)
  133. {
  134. maxI = i;
  135. maxArea = tempArea;
  136. }
  137. }
  138. printf("最大矩形的信息:\n");
  139. printf("左上角的坐标点为:第%d行第%d列\n",posArr[maxI][0],posArr[maxI][1]);
  140. printf("宽:%d,高%d\n",posArr[maxI][3]+1,posArr[maxI][2]+1);
  141. printf("面积为:%d\n",(posArr[maxI][3]+1)*(posArr[maxI][2]+1));
  142. return 0;
  143. }

效果演示:

 

 

拓展:

求正方形该代码也使用,查找 下方0个数和右边0个数一样的组合即可。

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号