首页 > 其他分享 >LeetCode/将石头分散到网格的最少移动次数

LeetCode/将石头分散到网格的最少移动次数

时间:2023-09-10 23:56:08浏览次数:43  
标签:cur 格子 int res 网格 石头 depth 最少 LeetCode

给你一个大小为 3 * 3 ,下标从 0 开始的二维整数矩阵 grid ,分别表示每一个格子里石头的数目。
网格图中总共恰好有 9 个石头,一个格子里可能会有多个石头。
每一次操作中,你可以将一个石头从它当前所在格子移动到一个至少有一条公共边的相邻格子。
请你返回每个格子恰好有一个石头的最少移动次数

1. 回溯法

贪心置换最大的

class Solution {
public:
    int dir[4][2] = {{1,0},{0,1},{-1,0},{0,-1}};
    int minimumMoves(vector<vector<int>>& grid) {
        string cur = "";
        string target = "111111111";
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
                cur.push_back(grid[i][j]+'0');
        cout<<cur;
        unordered_map<string,int> dp; //记录对应状态的次数,防止重复遍历
        function<int(int)> f = [&](int depth)->int{
            if(cur==target) return depth;
            if(dp.count(cur)&&dp[cur]<=depth) return INT_MAX/2;//无效,剪枝
            dp[cur] = depth;//记录该状态操作次数,剪枝

            int res = INT_MAX/2;
            int i = 0;
            for(int k = 0; k < 9; k++) //贪心置换最大的
                if(cur[k]>cur[i]) i = k;
            //if(cur[i]=='0'||cur[i]=='1') continue;
            int x = i/3; int y = i%3;
            for(int j=0;j<4;j++){
                int nx = x + dir[j][0]; int ny = y + dir[j][1];
                if(nx<0||nx>2||ny<0||ny>2) continue;
                int npos = nx*3 + ny;
                cur[i]--; cur[npos]++;
                res = min(res,f(depth+1));
                cur[i]++; cur[npos]--;
            }
            return res;
        };
        return f(0);
    }
};

2. 移入移出全排列匹配

class Solution {
public:
    int minimumMoves(vector<vector<int>>& grid) {
        vector<int> from,to;
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++){
                if(grid[i][j])
                    for(int k=1;k<grid[i][j];k++)
                        from.push_back(i*3+j);
                else to.push_back(i*3+j);
            }
        int res = INT_MAX;
        do{
            int cur = 0;
            for(int i=0;i<from.size();i++)//计算当前全部曼哈顿距离
                cur+=cal(from[i],to[i]);
            res = min(res,cur);
        }
        while(next_permutation(from.begin(),from.end()));
        return res;
    }
    int cal(int from,int to){
        int fx = from/3; int fy = from%3;
        int tx = to/3; int ty = to%3;
        return abs(fx-tx)+abs(fy-ty);
    }
};

标签:cur,格子,int,res,网格,石头,depth,最少,LeetCode
From: https://www.cnblogs.com/929code/p/17692306.html

相关文章

  • #yyds干货盘点# LeetCode程序员面试金典:翻转二叉树
    题目:给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。 示例1:输入:root=[4,2,7,1,3,6,9]输出:[4,7,2,9,6,3,1]示例2:输入:root=[2,1,3]输出:[2,3,1]示例3:输入:root=[]输出:[]代码实现:classSolution{publicTreeNodeinvertTree(TreeNoderoot){......
  • #yyds干货盘点# LeetCode程序员面试金典:第三大的数
    1.简述:给你一个非空数组,返回此数组中 第三大的数 。如果不存在,则返回数组中最大的数。 示例1:输入:[3,2,1]输出:1解释:第三大的数是1。示例2:输入:[1,2]输出:2解释:第三大的数不存在,所以返回最大的数2。示例3:输入:[2,2,3,1]输出:1解释:注意,要求返回第三大的数,是指在所......
  • LeetCode209.长度最小的子数组
    9月8日LeetCode209.长度最小的子数组https://leetcode.cn/problems/minimum-size-subarray-sum/description/学习内容题目的内容是给一个正整数的数组及目标值target,找到大于等于目标值的连续数组最小长度的区间。容易想到的方法是两层for来遍历,分别表示区间终止位置和区间起始位......
  • Leetcode刷题本地debug框架搭建
    思路1.初版cmake+单一.cpp文件参考:https://blog.songjiahao.com/archives/3622.改良版cmake+源文件、头文件(含List、Tree等数据结构)分离+gtest参考:https://github.com/Pokerpoke/LeetCode Normal模板以Leetcode1两数之和为例#include<iostream>#include......
  • LeetCode刷题笔记
    算法1.差分数组+前缀和1589.所有排列中的最大和-力扣(LeetCode)对于每一次遍历都有m个数需要加1,如果对这些数遍历,则需要O(m)复杂度,此时可以记录这m个数的差分数组:​ 这样就可以把时间复杂度缩小到O(1),之后求前缀和就可以得到原来的数组。2.线性筛(欧拉筛)求素数2601.质数减法......
  • #yyds干货盘点# LeetCode程序员面试金典:用栈实现队列
    题目:请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):实现 MyQueue 类:voidpush(intx) 将元素x推到队列的末尾intpop() 从队列的开头移除并返回元素intpeek() 返回队列开头的元素booleanempty() 如果队列为空,返回 true ......
  • #yyds干货盘点# LeetCode程序员面试金典:等差数列划分
    1.简述:如果一个数列 至少有三个元素 ,并且任意两个相邻元素之差相同,则称该数列为等差数列。例如,[1,3,5,7,9]、[7,7,7,7] 和 [3,-1,-5,-9] 都是等差数列。给你一个整数数组 nums ,返回数组 nums 中所有为等差数组的 子数组 个数。子数组 是数组中的一个连续序列。 示例1......
  • [刷题记录Day 23]Leetcode二叉树
    No.1题目修剪二叉搜索树思路递归法有点抽象,要对具体案例做模拟才好懂递归分析返回值:节点,参数:节点,[下界,上界]终止条件:遇到空节点,返回空单层递归逻辑:判断不在范围内的情况:当前节点小于下界/大于上界,直接返回右/左子树递归结果;若在范围内,则递归筛查左右子树,返回当前节点......
  • LeetCode207——课程表
    你这个学期必须选修 numCourses 门课程,记为 0 到 numCourses-1 。在选修某些课程之前需要一些先修课程。先修课程按数组 prerequisites 给出,其中 prerequisites[i]=[ai,bi] ,表示如果要学习课程 ai 则 必须 先学习课程  bi 。例如,先修课程对 [0,1] 表......
  • LeetCode297:hard级别中最简单的存在,java版,用时击败98%,内存击败百分之九十九
    本篇概览因为欣宸个人水平有限,在刷题时一直不敢面对hard级别的题目,生怕出现一杯茶一包烟,一道hard做一天的窘境这种恐惧心理一直在,直到遇见了它:LeetCode297,建议不敢做hard题的新手们速来围观,拿它练手,轻松找到自信题目简介二叉树的序列化与反序列化序列化是将一个数据......