LeetCode-day20-2850. 将石头分散到网格图的最少移动次数
- 题目描述
- 示例
- 示例1:
- 示例2:
- 思路
- 代码
题目描述
给你一个大小为 3 * 3 ,下标从 0 开始的二维整数矩阵 grid ,分别表示每一个格子里石头的数目。网格图中总共恰好有 9 个石头,一个格子里可能会有 多个 石头。
每一次操作中,你可以将一个石头从它当前所在格子移动到一个至少有一条公共边的相邻格子。
请你返回每个格子恰好有一个石头的 最少移动次数 。
示例
示例1:
输入:grid = [[1,1,0],[1,1,1],[1,2,1]]
输出:3
解释:让每个格子都有一个石头的一个操作序列为:
1 - 将一个石头从格子 (2,1) 移动到 (2,2) 。
2 - 将一个石头从格子 (2,2) 移动到 (1,2) 。
3 - 将一个石头从格子 (1,2) 移动到 (0,2) 。
总共需要 3 次操作让每个格子都有一个石头。
让每个格子都有一个石头的最少操作次数为 3 。
示例2:
输入:grid = [[1,3,0],[1,0,0],[1,0,3]]
输出:4
解释:让每个格子都有一个石头的一个操作序列为:
1 - 将一个石头从格子 (0,1) 移动到 (0,2) 。
2 - 将一个石头从格子 (0,1) 移动到 (1,1) 。
3 - 将一个石头从格子 (2,2) 移动到 (1,2) 。
4 - 将一个石头从格子 (2,2) 移动到 (2,1) 。
总共需要 4 次操作让每个格子都有一个石头。
让每个格子都有一个石头的最少操作次数为 4 。
思路
采用枚举全排列。
由于所有移走的石子个数等于所有移入的石子个数(即 0 的个数),我们可以把移走的石子的坐标记录到列表 _from 中(可能有重复的坐标),移入的石子的坐标记录到列表 _to 中。这两个列表的长度是一样的。
枚举 _from 的所有排列,与 _to 匹配,即累加从 _from[i] 到 _to[i] 的曼哈顿距离。
所有距离之和的最小值就是答案。
代码
class Solution:def minimumMoves(self, grid: List[List[int]]) -> int:_from = []_to = []for i,row in enumerate(grid):for j,val in enumerate(row):if val > 1:_from.extend([(i,j)] * (val-1))elif val == 0:_to.append((i,j))ans = inffor _from2 in permutations(_from):total = 0for (x1,y1),(x2,y2) in zip(_from2,_to):total += abs(x1-x2) + abs(y1-y2)ans = min(ans, total)return ans