首页 > 其他分享 >十二 167. 木棒 (回溯)

十二 167. 木棒 (回溯)

时间:2024-03-26 12:15:40浏览次数:20  
标签:剪枝 木棒 private int length static 回溯 167

167. 木棒 (回溯)
image

思路:把最长木棒长度作为初始,逐渐增减,使用dfs寻找最小的可能初始长度。
需要注意的点就是剪枝:

  1. 剪枝 1:sum % length == 0 只有 length 是 sum 的约数才有可能凑出多个等长的木棒
  2. 剪枝 2:优化搜索顺序,木棍长度从大到小排序,可以减少搜索的分支
  3. 排除等效冗余优化
    剪枝 3-1:确定每根木棒中木棍的枚举顺序,因为我们的方案和顺序没有关系,以组合的形式枚举方案可以少搜很多重复方案
    剪枝 3-2:如果当前木棍没有搜到方案,则跳过所有长度相等的木棍
    剪枝 3-3:如果是木棒的第一根木棍就搜索失败了,则一定搜不到方案
    剪枝 3-4:如果是木棒的最后一根木棍(+ 上它木棒长度正好是 length)搜索失败了,也一定搜不到方案
import java.util.*;

public class Main {
    private static int[] sticks;
    private static boolean[] used;
    private static int n;
    private static int sum;
    private static int length;
    
    private static boolean dfs(int u, int cur, int start) {
        if (u * length == sum) {
            return true;
        }
        if (cur == length) {
            return dfs(u + 1, 0, 0);
        }
        for (int i = start; i < n; i++) {
            if (used[i]) {
                continue;
            }
            if (cur + sticks[i] <= length) {
                used[i] = true;
                if (dfs(u, cur + sticks[i], i + 1)) {
                    return true;
                }
                used[i] = false;
            }
            if (cur == 0 || cur + sticks[i] == length) {
                return false;
            }
            int j = i + 1;
            while (j < n && sticks[j] == sticks[i]) {
                j++;
            }
            i = j - 1;
        }
        return false;
    }
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        while (n != 0) {
            sum = 0;
            length = 0;
            sticks = new int[n];
            for (int i = 0; i < n; i++) {
                sticks[i] = sc.nextInt();
                sum += sticks[i];
                length = Math.max(length, sticks[i]);
            }
            Arrays.sort(sticks);
            int left = 0, right = sticks.length - 1;
            while (left < right) {
                int temp = sticks[left];
                sticks[left] = sticks[right];
                sticks[right] = temp;
                left++;
                right--;
            }
            
            used = new boolean[n];
            while (true) {
                if (sum % length == 0 && dfs(0, 0, 0)) {
                    System.out.println(length);
                    break;
                }
                length++;
            }
            n = sc.nextInt();
        }
        
    }
}

标签:剪枝,木棒,private,int,length,static,回溯,167
From: https://www.cnblogs.com/he0707/p/18096357/lanqiaobei12

相关文章

  • BM56 有重复项数字的全排列(回溯)
    importjava.util.*;publicclassSolution{/***代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可***@paramnumint整型一维数组*@returnint整型ArrayList<ArrayList<>>*/publicvo......
  • Java回溯知识点(含面试大厂题和源码)
    回溯算法是一种通过遍历所有可能的候选解来寻找所有解的算法,如果候选解被确认不是一个解(或至少不是最后一个解),回溯算法会通过在上一步进行一些变化来丢弃这个解,即“回溯”并尝试另一个候选解。回溯法通常用递归方法来实现,在解决排列、组合、选择问题时非常有效。回溯算法的......
  • 算法打卡day25|回溯法篇05|Leetcode 491.递增子序列、46.全排列、47.全排列 II
     算法题Leetcode491.递增子序列题目链接:491.递增子序列大佬视频讲解:递增子序列视频讲解 个人思路和昨天的子集2有点像,但昨天的题是通过排序,再加一个标记数组来达到去重的目的。而本题求自增子序列,是不能对原数组进行排序的,因为排完序的数组都是自增子序列了。解决......
  • 【刷题笔记】回溯算法 - ⭐去重问题
    代码随想录讲解:代码随想录(programmercarl.com)只是在刷题过程中记录一下自己的想法,因为总是记不住去重逻辑。回溯算法:回溯法,一般可以解决如下几种问题:组合问题:N个数里面按一定规则找出k个数的集合切割问题:一个字符串按一定规则有几种切割方式子集问题:一个N个数的集合里有......
  • 代码学习第24天----回溯算法
    随想录日记part24time:time:time:2024.03.10主......
  • python coding with ChatGPT 打卡第23天| 回溯算法:理论基础
    文章目录视频讲解回溯法的效率解决的问题如何理解回溯法回溯框架视频讲解回溯算法理论篇回溯是递归的副产品,只要有递归就会有回溯。回溯法的效率回溯的本质是穷举,穷举所有可能,然后选出我们想要的答案,如果想让回溯法高效一些,可以加一些剪枝的操作,但也改不了回溯法......
  • 代码随想录 第二十四天| ●回溯 理论基础 ● 77. 组合
    回溯理论基础:回溯三部曲:制定回溯函数的参数和返回值确定回溯终止条件确定回溯遍历过程 回溯模板voidbacktracking(参数){if(终止条件){存放结果;return;}for(选择:本层集合中元素(树中节点孩......
  • 美国科技行业今年裁员超 5 万人;宁德时代一年净赚超 440 亿丨 RTE 开发者日报 Vol.167
       开发者朋友们大家好: 这里是「RTE开发者日报」,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享RTE(RealTimeEngagement)领域内「有话题的新闻」、「有态度的观点」、「有意思的数据」、「有思考的文章」、「有看点的会议」,但内容仅代表编辑的个人观......
  • 奇怪的回溯增加了 | leetcode131分割回文串
    题目要求:给你一个字符串s,请你将s分割成一些子串,使每个子串都是回文串。返回s所有可能的分割方案示例1:输入:s="aab"输出:[["a","a","b"],["aa","b"]]示例2:输入:s="a"输出:[["a"]]上述为常规做法,这里回溯的时候是i+1的,就很正常 这是我第一次做的时候自己憋出来......
  • 搜索与回溯算法
    排列#include<cstdio>#include<iostream>#include<algorithm>#include<iomanip>intvis[25],ans[25];intn;usingnamespacestd;voiddfs(intdep){if(dep==n+1){for(inti=1;i<=n;i++)cout<<setw(......