2850. 将石头分散到网格图的最少移动次数 Medium

给你一个大小为 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;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值