状态空间树

状态空间树:

就是问题的解空间树,分为子集树和排列树

子集树

当所给的问题是从n个元素组成的集合set中找到满足某一条件的一个子集时,相应的解空间树称为子集。
要注意,这个解空间树是一个虚拟的树,并不是构建出来的,如下面这颗树:
有三个物品n = 3,(类似于0-1背包问题)
xi = {0、1}表示第 i 个物品 ni 是否选中,
xi = 0 表示未选中,xi = 1表示选中

树有三层,第 i 层表示物品 ni,数字1、0表示 xi 的值
解空间树的所有可能,叶子上的个节点到A的路线代表了一个子集树——一种可能的解法
叶子上的个节点到A的路线代表了一个子集树——一种可能的解法,如 H 代表了111,表示n1、n2、n3都被选中,I表示110,n1、n2被选中,n3未被选中。
以下用两个例子来解释解空间树

0-1背包中使用穷举法

本文先从简单的穷举法开始介绍子集树
穷举法得到每一个子集树

  • 若当前为非叶节点
    将1压栈
    递归访问左子树
    (递归访问左子树递归到最后时,例如访问到 H 时,就要pop了)
    将0压栈
    递归访问右子树
    (递归访问右子树递归到最后时,例如访问到 I 时,就要pop了)
  • 若当前为叶节点
    顺序打印栈中内容
import java.util.Stack;

public class BruteForce {

	static Stack<Integer> stack = new Stack<>();

	static void subSetTree(int n) {
		if (n > 0) {
			stack.push(0);
			subSetTree(n - 1);
			stack.pop();
			stack.push(1);
			subSetTree(n - 1);
			stack.pop();
		} else {
			for (Integer integer : stack) {
				System.out.print(integer);
			}
			System.out.println();
		}
	}

	public static void main(String[] args) {
		subSetTree(3);
	}

}

排列树

TSP(Travelling Saleman Problem,货郎担、邮递员)问题、或者求全排列的问题。
以全排列为例:
定义:
设Set{S1, S2, S3,…, Sn}有 n 个元素,Seti = Set - {Si}
子集合 X 中元素的全排列记为 arrange(X),
(Si)arrange(Seti)表示在全排列arrange(Seti)的每一个排列前加上前缀Si得到的排列。
Seti表示Set中没有Si元素

Set的全排列可归纳如下
当n=1时,arrange(Set)=(S1),其中S1是集合Set中唯一的元素;
当n>1时,arrange(Set)由(S1)arrange(Set1),…, (Sn)arrange(Setn)构成。
实现思想
将整组数中的所有的数分别与第一个数交换,这样就总是在处理后n-1个数的全排列。

有ABC三个字母,求其全排列:
当n = 3,并且Set = {a,b,c},则:
arrange(Set)=a.arrange({b,c}) + b.arrange({a,c}) + c.arrange({a,b})
arrange({b,c})=b.arrange© + c.arrange(b)
a.arrange({b,c})=ab.arrange© + ac.arrange(b)
=ab.c + ac.b=(abc, acb)
全排列的状态空间树

全排列

public class Tsp {
	static int[] s;

	static void arrangeTree(int i, int n) {
		// 为什么是 i < n -1。因为最后一个不用交换了
		if (i < n - 1) {
			for (int j = i; j < n; j++) {
				// swap(s[i], s[j]);
				int k = s[j];
				s[j] = s[i];
				s[i] = k;
				arrangeTree(i + 1, n);
				// 这里swap,是因为arrangeTree(i + 1, n);前的swap影响了数组 s 的顺序。
				// swap(s[i], s[j]);
				k = s[j];
				s[j] = s[i];
				s[i] = k;
			}
		} else {
			for (int j : s) {
				System.out.print(j);
			}
			System.out.println();
		}
	}

	public static void main(String[] args) {
		int n = 3;
		s = new int[n];
		for (int i = 0; i < n; i++) {
			s[i] = i + 1;
		}
		arrangeTree(0, n);
	}

}

在这里插入图片描述

emmmm,全排列这个其实挺迷的

总结

  • 递归简单,但如何将问题分解成递归就不容易了
  • 递归的判出界限让人很迷
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值