首页 > 其他分享 >AcWing 167. 木棒 (剪枝非常多的一道搜索题

AcWing 167. 木棒 (剪枝非常多的一道搜索题

时间:2023-11-26 14:45:35浏览次数:34  
标签:剪枝 cur int len static 棍子 167 AcWing

package 算法提高课;

import java.util.Arrays;
import java.util.Scanner;

public class acw167 {
    static int[] w;
    static boolean[] st;
    static int sum, len, n;

    /**
     * 本题剪枝比较多光介绍一下, 本代码注释光介绍一下剪枝的大概思路, 如果有遗忘或者想要证明, 第一首选还是看题解和视频
     * */

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        while (sc.hasNext()) {
            n = sc.nextInt();
            if (n == 0) break;
            sum = 0;
            w = new int[n + 10]; st = new boolean[n + 10];

            for (int i = 1; i <= n; i ++ ) {
                w[i] = sc.nextInt();
                sum += w[i];
            }

            // 剪枝1 : 优化搜索顺序, 先枚举长的小木棍
            Arrays.sort(w, 1, 1 + n);
            reverse();

            len = 1;
            while (true) {
                // 剪枝2 : 可行性剪枝, 只有总长度是每一个长木棍的长度len的倍数的时候才会是答案
                if (sum % len == 0 && dfs(0, 0, 1)) {
                    System.out.println(len);
                    break;
                }
                len ++ ;
            }
        }
    }

    // 拼好了的u根长棍, 正在拼第u + 1根长棍, 当前长棍拼了cur长, 从start开始枚举小棍子
    private static boolean dfs(int u, int cur, int start) {
        if (u * len == sum) return true; // 长棍子都拼好的条件是 -> 长棍子的长度 * 拼好的根数 == 总长度
        if (cur == len) return dfs(u + 1, 0, 1);

        for (int i = start; i <= n; i ++ ) {
            if (st[i] || cur + w[i] > len) continue; // 如果这个棍子被用过了, 或者长度太长, 我们就不用

            st[i] = true;
            if (dfs(u, cur + w[i], i + 1)) return true; // 往下搜看这种方法成功不成功, 成功了就返回true,不成功就是走下面的看能不能剪枝
            st[i] = false;

            // 走到这里了就说明上面放棍子放失败了
            if (cur == 0 || cur + w[i] == len) return false; // 剪枝3 : 如果是我这根棍子放的位置是 第一根棍子 或者 末尾的最后一根棍子 的位置且无解, 那目前的方法就不可能有解, 直接返回false
            // 这里的证明太***了, 可以看视频或者题解

            int j = i;
            while (j <= n && w[j] == w[i]) j ++ ; // 剪枝4 : 排除等效冗余, 因为长度是降序, 并且如果我这根小棍子放了没解, 那和我一样长的小棍子放了同样无解
            i = j - 1; // 具体证明见视频或者题解
        }

        return false;
    }

    private static void reverse() {
        for (int i = 1, j = n; i < j; i ++ , j -- ) {
            int t = w[i];
            w[i] = w[j];
            w[j] = t;
        }
    }
}

标签:剪枝,cur,int,len,static,棍子,167,AcWing
From: https://www.cnblogs.com/llihaotian666/p/17857190.html

相关文章

  • AcWing 1129. 热浪 (dij板子题
    package算法提高课;importjava.util.Arrays;importjava.util.PriorityQueue;importjava.util.Scanner;publicclassacw1129{staticclassPIIimplementsComparable{intdis,tar;//tar表示我这条边的入弧,dis表示我这条边的距离publicP......
  • AcWing 1128. 信使 (dij板子题 + 求花费最大的那个点的花费
    package算法提高课;importjava.util.Arrays;importjava.util.PriorityQueue;importjava.util.Scanner;publicclassacw1128{staticintn,m;staticint[]h,e,w,ne;staticint[]d;staticboolean[]st;staticintidx;staticclas......
  • AcWing 蓝桥杯 3994. 阿坤老师的独特瓷器 (非常经典俄罗斯套娃问题
    package蓝桥杯;importjava.util.Arrays;importjava.util.Scanner;publicclasslanqiao3994{/***思路:*固定套路了感觉,先按直径从大到小排,然后直径相同的再按高度从小到大排*然后从前往后遍历的时候就可以在一定存在更大d的前......
  • AcWing 3305. 作物杂交 (spfa建边变形版本
    package蓝桥杯;importjava.util.Arrays;importjava.util.LinkedList;importjava.util.Queue;importjava.util.Scanner;publicclasslanqiao1443{staticfinalintN=2010,M=2*100010;staticint[]h,e,ne,w,target;staticint[]dist;......
  • AcWing 903. 昂贵的聘礼 (超级源点 + 等级限制 + 抽象建图
    package算法提高课;importjava.util.Arrays;importjava.util.Scanner;publicclassacw903{staticintm,n;staticint[]dis,level;staticboolean[]st;staticint[][]g;/**思路:首先用到了虚拟源点,加入了等级限制*......
  • 对acwing193的解释
    首先是估价函数的解释由于\(x\)较大,所以\(x\)一直平方是最快的能到达\(p\)及以上的方法,所以这个估价函数比实际代价小(或等)再看\(gcd\)这个剪枝把八种情况列出,如果\(x\)和\(y\)都是\(gcd=d\)的倍数,那么加减或翻倍之后的新的\(x\)和\(y\)一定也是\(d\)的倍数,所以可以剪枝......
  • acwing 第 130 场周赛  (前缀和,dfs,对不同边的处理)
      #include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<climits>usingnamespacestd;typedeflonglongLL;constintN=5010;intn;inta[N];LLs[N];LLget(intl,intr){return......
  • CSE 167 3DOpenGL 开发
    我们将在本作业中开发一个用于检查3D模型的交互式界面。正如您可能从以前的家庭作业中了解到的那样,渲染需要在数百万像素和数十亿三角形。这会给性能带来重大挑战,尤其是在我们希望与内容实时交互。为了让事情变得更快,计算机图形学的先驱们提出了使用特定领域硬件加速渲染的解决......
  • AcWing 算法基础课week 1 总结(万字长文)
    AcWing算法基础课week1总结总结点1:快速排序(分治思想)题1:从小到大排序主体思路:定义一个数x属于数组s,利用双指针,将数组分为大于等于x和小于等于x的两部分,然后递归处理。(具体步骤如下)1.如上图所示,我们定义一个数组s用来储存n个数据,然后定义两个指针ij,分别指向数组的左右两......
  • Acwing.第130场周赛
    Acwing.第130场周赛比赛链接A.最大数和最小数题目链接思路:简单模拟,使用max()和min()函数就可以了代码:#include<bits/stdc++.h>usingnamespacestd;voidsolve(){ inta,b,c; cin>>a>>b>>c; cout<<max(a,max(b,c))<<""<<min(a,min(b,c))<......