剪枝

暴力破解的缺点:

  • 循环次数过多
  • 多层循环容易造成分支数爆炸
  • 递归也会引发指数增长

剪枝:

  • 尽早结束无意义的运算分支
  • 尽量选择分支少的为循环条件
  • 优点: 提高计算速度和效率

实例分析:

1.已知要找的总额,和提供的各种面值

例如:要找8元零钱,可以使用5元,2元,1元和5角组合。

代码:

public static void main(String[] args) {
        int sum = 80;
        for (int a = 0; a <= sum / 50; ++a) {
            for (int b = 0; b <= sum / 20; ++b) {
                for (int c = 0; c <= sum / 10; ++c) {
                    for (int d = 0; d <= sum / 5; ++d) {
                        if (a * 50 + b * 20 + c * 10 + d * 5 == sum) {
                            System.out.println(a + "," + b + "," + c + "," + d);
                        }
                    }
                }
            }
        }
    }

这个问题本身不复杂,但是如果将问题复杂化,例如:要找800元零钱,有几十种零钞。循环嵌套的层数就会很深,计算的时间就会非常久。

剪枝版:

public static void main(String[] args) {
        int sum = 80;
        for (int a = 0; a <= sum / 50; ++a) {
            for (int b = 0; b <= sum / 20; ++b) {
                if (80 - 50 * a - 20 * b < 0)  //剪枝
                    break;
                for (int c = 0; c <= sum / 10; ++c) {
                    int d = (sum - a * 50 - b * 20 - c * 10);
                    if (d < 0)  //剪枝
                        break;
                    d = d / 5; // d直接根据a,b,c的结果计算
                    if (a * 50 + b * 20 + c * 10 + d * 5 == sum) {
                        System.out.println(a + "," + b + "," + c + "," + d);
                    }

                }
            }
        }
    }

2. n位数的平方的尾数是n位数本身

代码:

public static void main(String[] args) {
        for (int i = 100; i < 1000; ++i)
        {
            int n = i * i;  // 3位数的平方    
            int m = n % 1000; // 3位数平方的尾数
            if  (m == i)
                System.out.println(i+"," + n);
        }
    }

剪枝版:

public static void main(String[] args) {
        for (int i = 100; i < 1000; ++i)
        {
            int n = i * i;        // 三位数的平方
            int m = n % 1000; // 3位数平方的尾数
            int geWei = n % 10;  // 三位数平方后的个位
            // 剪枝 过滤
            if (geWei != 0 && geWei != 1 && geWei != 5 && geWei != 6) {
                continue;
            }
            if  (m == i)
                System.out.println(i+"," + n);
        }
    }

 3.观察下面的算式:

△△△ * △△ = △△△△

某3位数乘以2位数,结果为4位数

要求:在9个△所代表的数字中,1~9的数字恰好每个出现1次

代码:

public static void main(String[] args) {
    {
        long beginTime = System.currentTimeMillis();
        int n1, n2, n3, n4, n5, n6, n7, n8, n9;
        for (int i = 12; i <= 98; ++i) {
            n1 = i / 10;
            n2 = i % 10;
            if (n2 == 0 || n1 == n2)
                continue;
            for (int j = 123; j <= 987; ++j) {
                n3 = j / 100;
                n4 = j / 10 % 10;
                n5 = j % 10;
                if (n4 == 0 || n5 == 0)
                    continue;
                if (n3 == n4 || n3 == n5 || n4 == n5)
                    continue;
                if (n3 == n1 || n3 == n2 || n4 == n1 || n4 == n2 || n5 == n1
                        || n5 == n2)
                    continue;

                int k = i * j;
                if (k < 1234 || k > 9876)
                    continue;

                n6 = k / 1000;
                n7 = k / 100 % 10;
                n8 = k / 10 % 10;
                n9 = k % 10;
                if (n7 == 0 || n8 == 0 || n9 == 0)
                    continue;
                if (n6 == n7 || n6 == n8 || n6 == n9 || n7 == n8 || n7 == n9
                        || n8 == n9)
                    continue;
                if (n6 == n1 || n6 == n2 || n6 == n3 || n6 == n4 || n6 == n5)
                    continue;
                if (n7 == n1 || n7 == n2 || n7 == n3 || n7 == n4 || n7 == n5)
                    continue;
                if (n8 == n1 || n8 == n2 || n8 == n3 || n8 == n4 || n8 == n5)
                    continue;
                if (n9 == n1 || n9 == n2 || n9 == n3 || n9 == n4 || n9 == n5)
                    continue;

                System.out.println(j + "," + i + "," + k);

            }
        }

        long endTime = System.currentTimeMillis();
        System.out.println("用时: " + (endTime - beginTime) + " ms");
    }
View Code

效果:

使用HashSet

public static void main(String[] args) {
        Set<Integer> set = new HashSet<Integer>();
        int n1, n2, n3, n4, n5, n6, n7, n8, n9;
        long beginTime = System.currentTimeMillis();

        for (int i = 123; i <= 987; ++i) {
            set.clear();
            n1 = i / 100;
            n2 = i / 10 % 10;
            n3 = i % 10;
            if (n2 == 0 || n3 == 0) // 不能为0
                continue;
            if (n1 == n2 || n1 == n3 || n2 == n3) // 不能重复
                continue;

            set.add(n1);
            set.add(n2);
            set.add(n3);

            for (int j = 12; j <= 98; ++j) {
                n4 = j / 10;
                n5 = j % 10;
                if (n5 == 0)
                    continue;
                if (n4 == n5)
                    continue;
                if (set.contains(n4) || set.contains(n5))
                    continue;

                int k = i * j;
                if (k < 1234 || k > 9876)
                    continue;

                n6 = k / 1000;
                n7 = k / 100 % 10;
                n8 = k / 10 % 10;
                n9 = k % 10;

                if (n6 == 0 || n7 == 0 || n8 == 0 || n9 == 0) {
                    continue;
                }
                if (n6 == n7 || n6 == n8 || n6 == n9 || n7 == n8 || n7 == n9
                        || n8 == n9) {
                    continue;
                }
                set.add(n4);
                set.add(n5);

                if (set.contains(n6) || set.contains(n7) || set.contains(n8)
                        || set.contains(n9)) {
                    set.remove(n4);
                    set.remove(n5);
                    continue;
                }

                System.out.println(i + "," + j + "," + k);

                set.remove(n4);
                set.remove(n5);
            }

        }
        long endTime = System.currentTimeMillis();
        System.out.println("总计用时:" + (endTime - beginTime) + "ms");

    }
View Code

效果:

原文地址:https://www.cnblogs.com/hupeng1234/p/6818857.html