回溯法,并用回溯法请求0/1背包问题和皇后问题

本文介绍了回溯法的概念及其如何应用于解决0/1背包问题和皇后问题。通过将问题的可能解空间转换为树结构,使用深度优先搜索来寻找解。文中给出了使用Java实现的0/1背包问题和四皇后问题的代码示例,并展示了不同问题的解数量。
摘要由CSDN通过智能技术生成
穷举法是所有最优化问题和多解问题的通用解法。在用穷举法求解的过程中,很多候选的解可以在求解中途被约束条件淘汰点,从而降低求解的复杂度。基于这种思想引出了回溯法。

回溯法是穷举法的一个改进,因为它也是一种通用的算法。一个问题可能会有多种可能解,这些可能解构成的问题的可能解空间, 可能解空间不是解的集合而是可能解的集合,解空间是可能解的一个子集。问题的解会从解空间中出。回溯法的基本思想是将问题的可能解空间转换成一颗树,使得这棵树的一个路径就是这个问题的一个可能解,这个树的所有路径就是这个问题的可能解空间。之后运用深度优先算法去遍历解空间树,假设遍历到某个节点时这个节点已经不符合约束条件或者不能满足最优条件,则不再搜索这个节点的所有子节点了,从而降低的计算的复杂度。但是前提是这个问题的解要能满足:假设(x0, x1, x2)是问题的可能解空间,当x0=某个确定值时,已经不满足条件,那么接下来,不管x1和x1取任何值也不能满足条件, 从而不用再从x0在往下所搜索。

例子两个经典问题;
1、0/1背包问题,假设有n个物品,重量和价值都确定,背包的重量也确定,求在背包不超重的前提下,最多能带多少价值的物品?
2、皇后问题,假设n*n的一个棋盘放置n个皇后,n个皇后都不能在同一个行,同一列,同一个对角线,问总共有多少种摆法?
 
用回溯法求解:
0/1背包问题的可能解空间是(x0, x1,x2),假设n = 3;其中x0,x1,x2取值都为0或1,表示物品0,物品1,物品2,是否有在背包中,1表示在,0表示不在。将可能解空间换成树,树的一个路径就是一个可能解,如图所示为树的结构,之后求解。经满足条件的解保存,并排序选出最优解。
     


2、皇后问题假设n = 4;则可能解空间为(x0, x1, x2, x3)其中xi取值为0到3,xi表示第i行皇后放置的位置,将转换为树,即可用广度优先遍历的思想去求解。


代码实现:

控制台输出:
背包所盛放物品的最大价值为:
60
所盛放物品编号为
[1, 2]

代码:
package AlgorithmTest;

import java.util.ArrayList;
import java.util.Collections;

/**
 * Created by dell on 2016/12
 *用回溯法求解01背包问题,回溯法可以求解最优解问题和求出多个符合要求的解。关键是要讲问题的解空间转换成数,使得树的一条路径就是一个解。.
 */
public class BagProblem {
    public static void main(String[] args) {
        int[] weights =  new int[]{ 181416}; //三个物品的重量
        int[] vaules =  new int[]{ 483030}; //三个物品的价值
        int bagHodler =  30; //bag的承重为30,想要知道将将那些物品放入bag中能使价值最大,且不超重
        SolveSpaceTree solveSpaceTree =  new SolveSpaceTree(weights, vaules, bagHodler);
        Result result = solveSpaceTree.getSolve();
        System. out.println( "背包所盛放物品的最大价值为:");
        System. out.println(result. value);
        System. out.println( "所盛放物品编号为");
        System. out.println(result. ojectNos.toString());


    }

    //解空间树
    private static class SolveSpaceTree{
        private int  bagHolder;
        private TreeNode[]  nodes;
        public SolveSpaceTree( int[] weights,  int[] values,  int bagHodler){
            this. bagHolder = bagHodler;
            nodes new TreeNode[( int)Math. pow( 2, weights. length 1) -  1];
            nodes[ 0] =  new TreeNode(- 1false00); //第一个节点是空几点不代表哪个物品
            int index =  1;
            for ( int i =  0; i < weights. length; i++){
                for ( int j =  0; j <= i; j++){
                    nodes[index++] =  new TreeNode(i,  false, weights[i], values[i]);
                    nodes[index++] =  new TreeNode(i,  true, weights[i], values[i]);
                }
            }
        }
        public Result getSolve(){
            ArrayList<Result> results =  new ArrayList<Result>();
            getSolve( 0new Result(), results);
            Collections. sort(results);
            return results.get(results.size() -  1);
        }
        public void getSolve( int node, Result result, ArrayList<Result> results){
            if (node >=  nodes. length){
                results.add(result);
                return ;
            }

            int currentWeight =  nodes[node]. occurnodes[node]. weight0;
            int currentValue =  nodes[node]. occurnodes[node]. value0;
            if (currentWeight + result. weightSum <=  this. bagHolder){ //符合约束条件,往下走
                if ( nodes[node]. occur){
                    Result result1 =  new Result();
                    result1. weightSum = currentWeight + result. weightSum;
                    result1. value = currentValue + result. value;
                    result1. ojectNos.addAll(result. ojectNos);
                    result1. ojectNos.add( nodes[node]. objectNo);
                    getSolve( * node +  ,result1, results);
                    getSolve( * node +  ,result1, results);
                } else{
                    getSolve( * node +  ,result, results);
                    getSolve( * node +  ,result, results);
                }
            } else{
                if (result. weightSum <=  this. bagHolder){
                    results.add(result);
                }
            }
        }


    }

    public static class Result  implements Comparable<Result>{
        private int  weightSum 0;
        private int  value 0;
        private ArrayList<Integer>  ojectNos new ArrayList<Integer>();
        @Override
        public int compareTo(Result o){
            return this. value - o. value;
        }
    }

    public static class TreeNode{
        private boolean  occur; //出现与否
        private int  weight; //重
        private int  value; //价值
        private int  objectNo; //节点代码的物品

        public TreeNode( int objectNo,  boolean occur,  int weight,  int value) {
            this. occur = occur;
            this. weight = we
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值