给你一个大小为 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 。
提示:
·grid.length == grid[i].length == 3
·0 <= grid[i][j] <= 9
·grid
中元素之和为 9
。
题目大意:计算将每个格子中多出的石头填满所有空白格子所需的最少移动次数。
分析:
(1)可以用数组stones保存所有多出的石头的位置,用数组empty保存所有空白格子的位置,由于多出的石头刚好能够填满空白格子,所以数组stones和数组empty的大小相同;
(2)由(1)可知题目可转化为每次从stones和empty中各取出一个位置,然后将移动次数step加上这两个位置间的距离,重复上述操作直至两个数组为空,计算step可得的最小值;
(3)根据(2)设计算法,枚举stones的所有排列,对于每个排列在遍历的过程中将step加上stones[i]和empty[i]的距离,所有排列中step的最小值即为所得的最少移动次数。
class Solution {
public:int minimumMoves(vector<vector<int>>& grid) {int ans=INT_MAX,num;vector<pair<int,int>> stones,empty;for(int i=0;i<3;++i){for(int j=0;j<3;++j){num=grid[i][j];if(num>1) for(int k=1;k<num;++k) stones.emplace_back(i,j);else if(!num) empty.emplace_back(i,j);}}int N=stones.size();while(1){num=0;for(int i=0;i<N;++i){num+=abs(stones[i].first-empty[i].first)+abs(stones[i].second-empty[i].second);}ans=min(ans,num);if(!next_permutation(stones.begin(),stones.end())) break;}return ans;}
};