递归回溯求助!

发布于 2024-11-03 13:03:22 字数 3237 浏览 1 评论 0原文

我有点为难了。我必须实现一个递归回溯算法,该算法将找出如何以最少的浪费来切割条形。

这是来自课程作业的规范。

引用: 现在,想象一下这样的场景:一家工厂生产长度为 150 毫米的钢筋。其切割车间收到棒材切割长度的订单,必须通过切割制造的棒材来满足该订单。对于每个订单,工厂都希望以产生最少浪费的方式切割棒材。

开发一种 java 方法,给定长度为 150mm 的已制造棒材、订单列表中所有订单的集合和一个空集,生成可以通过以最小浪费切割棒材来满足的订单集。 目前我已经让它以非递归方式工作,但不是 100%,当我尝试让它以递归方式工作时,我认为它只是崩溃了,哈哈,无限循环/堆栈溢出。

有人介意查看我的代码并帮助我吗?这是大学课程,也是我第一次真正尝试递归回溯,所以任何帮助都会很棒。

非递归代码可以工作。

代码:

private SetInt tryCutting(SetInt possibleOrders, SetInt solution, int lengthLeft)
    {
        //SetInt possibleOrders = solution.clone();


        while(!possibleOrders.isEmpty())
        {

            if(possibleOrders.min()<= lengthLeft)
            {
                if(possibleOrders.min() > solution.min())
                {
                System.out.println(possibleOrders.min() + "added to solution \n");
                solution.add(possibleOrders.min());
                lengthLeft -= possibleOrders.min();
                possibleOrders.remove(possibleOrders.min());
                }
                else
                {
                    possibleOrders.remove(possibleOrders.min());
                }
                try{
                        Thread.sleep(10); //sleep 1000 milliseconds
                        }catch(Exception e){}
            }


            else if(possibleOrders.min() > lengthLeft)
            {
                System.out.println("poss order min" + possibleOrders.min()+"\n");
                System.out.println("solution min" + solution.min()+"\n");
                if(possibleOrders.min() > solution.min())
                {
                    int value = possibleOrders.min();
                    while(value > lengthLeft)
                    {
                        lengthLeft += solution.min();
                        System.out.println(solution.min() + "added to possible orders \n");
                        possibleOrders.add(solution.min());
                        solution.remove(solution.min());
                    }
                    solution.add(value);
                    possibleOrders.remove(value);
                    lengthLeft -= value;
                }
                else
                {
                    possibleOrders.remove(possibleOrders.min());
                }
            }

        }
        System.out.print("Solution :");
        solution.printNumbers();
        System.out.println("Wastage :" + lengthLeft);
        return solution;
    }

我对递归代码的尝试

private SetInt tryCutting(SetInt possibleOrders, SetInt solution, int lengthLeft)
    {
        while(!possibleOrders.isEmpty())
        {
            System.out.println("not empty");
            int value = possibleOrders.min();
            if(value < lengthLeft && value>solution.min())
            {
                solution.add(value);
                possibleOrders.remove(value);
                lengthLeft-=value;

                if(!possibleOrders.isEmpty())
                {
                    possibleOrders.tryCutting(possibleOrders,solution,lengthLeft);
                }
                else
                    break;
            }
        }
        return solution;
    }

I'm in abit of a pickle. I've got to implement a recursive backtracking algorithm that will work out how to cut a bar with the least ammount of wasteage.

this is from the specification for the coursework.

Quote:
Now, imagine the scenario in which a factory manufactures steel bars of length 150mm. Its cutting shop receives orders for cut lengths of bars, which must be met by cutting up the manufactured bars. With each order the factory wants to cut the bar is such a way that it produces the least amount of wastage.

Develop a java method which given manufactured bar of length 150mm, a set of all orders in the order list and an empty set produces the set of orders which can be met by cutting up the bar with minimum wastage.
currently I've sort of got it working non recursively but not 100% and when I try and get it working recurisvely it just crashed lol infinite loop / stack overflow I think.

Would anyone mind looking at my code and giving me a hand? its for uni coursework and its the first time i've really tryed recursive backtracking so any help would be brilliant.

Non recursive code that sort of works.

Code:

private SetInt tryCutting(SetInt possibleOrders, SetInt solution, int lengthLeft)
    {
        //SetInt possibleOrders = solution.clone();


        while(!possibleOrders.isEmpty())
        {

            if(possibleOrders.min()<= lengthLeft)
            {
                if(possibleOrders.min() > solution.min())
                {
                System.out.println(possibleOrders.min() + "added to solution \n");
                solution.add(possibleOrders.min());
                lengthLeft -= possibleOrders.min();
                possibleOrders.remove(possibleOrders.min());
                }
                else
                {
                    possibleOrders.remove(possibleOrders.min());
                }
                try{
                        Thread.sleep(10); //sleep 1000 milliseconds
                        }catch(Exception e){}
            }


            else if(possibleOrders.min() > lengthLeft)
            {
                System.out.println("poss order min" + possibleOrders.min()+"\n");
                System.out.println("solution min" + solution.min()+"\n");
                if(possibleOrders.min() > solution.min())
                {
                    int value = possibleOrders.min();
                    while(value > lengthLeft)
                    {
                        lengthLeft += solution.min();
                        System.out.println(solution.min() + "added to possible orders \n");
                        possibleOrders.add(solution.min());
                        solution.remove(solution.min());
                    }
                    solution.add(value);
                    possibleOrders.remove(value);
                    lengthLeft -= value;
                }
                else
                {
                    possibleOrders.remove(possibleOrders.min());
                }
            }

        }
        System.out.print("Solution :");
        solution.printNumbers();
        System.out.println("Wastage :" + lengthLeft);
        return solution;
    }

My attempt at recursive code

private SetInt tryCutting(SetInt possibleOrders, SetInt solution, int lengthLeft)
    {
        while(!possibleOrders.isEmpty())
        {
            System.out.println("not empty");
            int value = possibleOrders.min();
            if(value < lengthLeft && value>solution.min())
            {
                solution.add(value);
                possibleOrders.remove(value);
                lengthLeft-=value;

                if(!possibleOrders.isEmpty())
                {
                    possibleOrders.tryCutting(possibleOrders,solution,lengthLeft);
                }
                else
                    break;
            }
        }
        return solution;
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

三生路 2024-11-10 13:03:22

这是我的解决方案。我没有使用集合,因为这会禁止订单多次出现相同的柱长度。不过,很容易将此示例改编为带有集合的版本。

import java.util.ArrayList;
import java.util.Arrays;

public class SteelMill {

    private int maximumLength;
    private Order best;

    public SteelMill() {
        Order ordered = new Order(3, 4, 1, 6, 2, 5);
        Order filled = new Order();
        maximumLength = 7;
        fillOrder(ordered, filled, 0);
        System.out.println("best solution found: " + best + " waste = "
                + (maximumLength - best.total()));
    }

    private void fillOrder(Order ordered, Order filled, int depth) {
        print(depth, "ordered = " + ordered + " filled = " + filled);
        depth++;
        if (filled.total() > maximumLength) {
            return;
        }
        if (filled.total() == maximumLength || best == null
                || filled.total() > best.total()) {
            best = filled;
            if (filled.total() == maximumLength) {
                System.out.println("perfect solution found: " + filled);
            }
        }
        for (Integer bar : ordered) {
            Order childOrdered = new Order(ordered);
            childOrdered.remove(bar);
            Order childFilled = new Order(filled);
            childFilled.add(bar);
            fillOrder(childOrdered, childFilled, depth);
        }
    }

    public class Order extends ArrayList<Integer> {
        private static final long serialVersionUID = 1L;

        public Order(Order toCopy) {
            super(toCopy);
        }

        public Order(Integer... values) {
            for (Integer value : values) {
                add(value);
            }
        }

        public int total() {
            int total = 0;
            for (Integer value : this) {
                if (value != null) {
                    total += value;
                }
            }
            return total;
        }

        public String toString() {
            return Arrays.toString(toArray());
        }
    }

    private static void print(int depth, String msg) {
        StringBuilder tabs = new StringBuilder();
        for (int i = 0; i < depth; i++) {
            tabs.append("  ");
        }
        System.out.println(tabs + msg);
    }

    public static void main(String[] args) {
        new SteelMill();
    }
}

Here's my solution. I didn't use sets because that would prohibit orders with multiple occurrences of the same bar length. It's easy to adapt this example to a version with sets though.

import java.util.ArrayList;
import java.util.Arrays;

public class SteelMill {

    private int maximumLength;
    private Order best;

    public SteelMill() {
        Order ordered = new Order(3, 4, 1, 6, 2, 5);
        Order filled = new Order();
        maximumLength = 7;
        fillOrder(ordered, filled, 0);
        System.out.println("best solution found: " + best + " waste = "
                + (maximumLength - best.total()));
    }

    private void fillOrder(Order ordered, Order filled, int depth) {
        print(depth, "ordered = " + ordered + " filled = " + filled);
        depth++;
        if (filled.total() > maximumLength) {
            return;
        }
        if (filled.total() == maximumLength || best == null
                || filled.total() > best.total()) {
            best = filled;
            if (filled.total() == maximumLength) {
                System.out.println("perfect solution found: " + filled);
            }
        }
        for (Integer bar : ordered) {
            Order childOrdered = new Order(ordered);
            childOrdered.remove(bar);
            Order childFilled = new Order(filled);
            childFilled.add(bar);
            fillOrder(childOrdered, childFilled, depth);
        }
    }

    public class Order extends ArrayList<Integer> {
        private static final long serialVersionUID = 1L;

        public Order(Order toCopy) {
            super(toCopy);
        }

        public Order(Integer... values) {
            for (Integer value : values) {
                add(value);
            }
        }

        public int total() {
            int total = 0;
            for (Integer value : this) {
                if (value != null) {
                    total += value;
                }
            }
            return total;
        }

        public String toString() {
            return Arrays.toString(toArray());
        }
    }

    private static void print(int depth, String msg) {
        StringBuilder tabs = new StringBuilder();
        for (int i = 0; i < depth; i++) {
            tabs.append("  ");
        }
        System.out.println(tabs + msg);
    }

    public static void main(String[] args) {
        new SteelMill();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文