一、题目
从前有个村庄,村民们喜欢在各种田地上插上小旗子,
旗子上标识了各种不同的数字。
某天集体村民决定将覆盖相同数字的
最小矩阵形的土地分配给村里做出巨大贡献的村民,
请问此次分配土地,
做出贡献的村民种最大会分配多大面积?
二、输入
第一行输入 m 和 n,
m 代表村子的土地的长
n 代表土地的宽
第二行开始输入地图上的具体标识
三、输出
此次分配土地,做出贡献的村民中
最大会分配多大面积
四、示例
示例一
输入:
3 3
1 0 1
0 0 0
0 1 0
输出:
9
- 说明:土地上的旗子为1,其坐标分别为 (0,0),(2,1)以及(0,2), 为了覆盖所有旗子,矩阵需要覆盖的横坐标为0和2,纵坐标为0和2,所以面积为9,即(2-0+1)*(2-0+1)= 9
示例二
输入:
3 3
1 0 2
0 0 0
0 3 4
输出:
1
- 说明:由于不存在成对的小旗子,故而返回1,即一块土地的面积。
五、题解
- 刚开始想用 DFS 或者 BFS 来解决,因为相同元素不一定相邻,不太好实现
- 暴搜遍历统计每个数字的边界;遍历完再计算每个数字对应的面积并更新最大面积
5.1 Java 实现
package org.stone.study.algo.ex202411;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class MaxArea {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int m = scanner.nextInt();
int n = scanner.nextInt();
// 需要显式读取行尾的换行符
scanner.nextLine();
int[][] grid = new int[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
grid[i][j] = scanner.nextInt();
}
//
scanner.nextLine();
}
int ans = maxArea(m, n, grid);
System.out.println(ans);
}
/**
* 最大面积
* @param m 行数
* @param n 列数
* @param grid 矩阵
* @return 最大面积
*/
public static int maxArea(int m, int n, int[][] grid) {
// 记录每个数字的最小行、最大行、最小列、最大列
Map<Integer, int[]> map = new HashMap<>();
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (grid[i][j] != 0) {
if(map.containsKey(grid[i][j])) { // 再次出现更新边界
int[] arr = map.get(grid[i][j]);
arr[0] = Math.min(arr[0], i); // 最小行
arr[1] = Math.max(arr[1], i); // 最大行
arr[2] = Math.min(arr[2], j); // 最小列
arr[3] = Math.max(arr[3], j); // 最大列
map.put(grid[i][j], arr);
} else { // 第一次出现初始化边界
map.put(grid[i][j], new int[]{i, i, j, j}); // 最小行,最大行,最小列,最大列
}
}
}
}
// 计算每个数字的面积并更新最大面积
int maxArea = 0;
for (Map.Entry<Integer, int[]> entry : map.entrySet()) {
int[] arr = entry.getValue();
int area = (arr[1] - arr[0] + 1) * (arr[3] - arr[2] + 1);
maxArea = Math.max(maxArea, area);
}
return maxArea;
}
}
5.2 Python实现
def maxArea(grid):
m, n = len(grid), len(grid[0])
# 记录每个数字的边界
bounds = {}
for i in range(m):
for j in range(n):
flag = grid[i][j]
if flag == 0:
continue
if flag not in bounds:
bounds[flag] = [i, i, j, j]
else:
bounds[flag][0] = min(bounds[flag][0], i)
bounds[flag][1] = max(bounds[flag][1], i)
bounds[flag][2] = min(bounds[flag][2], j)
bounds[flag][3] = max(bounds[flag][3], j)
# 计算每个数字的面积和最大面积
res = 0
for min_row, max_row, min_col, max_col in bounds.values():
res = max(res, (max_row - min_row + 1) * (max_col - min_col + 1))
return res
if __name__ == "__main__":
m, n = map(int, input().split())
grid = [list(map(int, input().split())) for _ in range(m)]
res = maxArea(grid)
print(res)