回溯法

           (1)搜索子集树

                    1.适用问题:求子集、0-1背包问题(实际上就是求组合的问题

                    2.子集树

                        

                       其中1表示选择,0表示不选。每一层各个节点其实表示的是集合中同一个元素的选择情况,如{1,3,5},A表示元素1选择或者不选的情况,B表示选择1之后,3选与不选的情况,C表示1不选之后3选与不选的情况


                 3.算法框架

void backtrack(int t){
    if(t>=n)
        Output(x);
    else
        for(i=0;i<1;i++){
            x[t]=i;
            if(Constraint(t) && Bound(t))
                backtrack(t+1);
        }
}
                      其中,x是01数组,x[t]=1表示集合中第t个元素在子集中,0表示 不在

                      Output(x):输出这个01数组,也就是对应的一个子集

                      Constraint(t):用来检验t是否能加入子集中,这和具体问题有关

                      原理:分别设置x[t]=0和x[t]=1,然后分别向下递归


                   4.例一:求集合的所有子集

	private static void subset(int t, int[] a, int[] x) 
	{
		if(t>=a.length)//表示所有元素都已经递归完毕
		{
			for(int i=0; i<x.length; i++)
			{
				if(x[i] != 0)
					System.out.print(a[i]+" ");
			}
			System.out.println();
		}
		else
		{
			x[t] = 1;//搜索左子树
			subset(t+1,a,x);
			x[t] = 0;//搜索右子树
			subset(t+1,a,x);
		}
	}

		int[] a = {1,3,5};
		int[] x = new int[a.length];
		subset(0,a,x);//从第一个元素开始

结果为:

1 3 5 
1 3 
1 5 
1 
3 5 
3 
5 

                   5.例二:0-1背包

		int n = 3;
		int v = 10;
		int[] weight = {3,4,5};
		int[] value = {4,5,6};
		
		int[] x = new int[n];
		int[] bestPlan = new int[n];
		int curValue = 0;
		int curWeight = 0;
		
		oneZeroPackage(0,weight,value,x,curValue,curWeight,v,bestPlan);
		
		System.out.println(maxValue);
		for(int i=0;i<bestPlan.length;i++)
		{
			if(bestPlan[i] != 0)
				System.out.print(value[i]+" ");
		}

	private static void oneZeroPackage(int t, int[] weight, int[] value,
			int[] x, int curValue, int curWeight, int maxWeight, int[] bestPlan) 
	{
		if(t>=weight.length)
		{
			if(curValue>maxValue)
			{
				for(int i=0; i<weight.length; i++)
					bestPlan[i] = x[i];
				maxValue = curValue;
			}
		}
		else
		{
			x[t] = 1;
			if(weight[t]+curWeight<=maxWeight)
				oneZeroPackage(t+1, weight, value, x, curValue+value[t], curWeight+weight[t], maxWeight, bestPlan);
			x[t] = 0;
			oneZeroPackage(t+1, weight, value, x, curValue, curWeight, maxWeight, bestPlan);
			
		}
	}

结果为:

11
5 6


           (2)求排列

                    

    @Test
    public void tests() throws UnsupportedEncodingException
    {
        int[] a = {1,3,5};

        pailie(a, 0, a.length-1);
    }
    
    private void pailie(int[] a, int begin, int end)
    {
        if (begin>end) {
            for (int i : a) {
                System.out.print(i+" ");
            }
            System.out.println();
        }else {
            for (int i = begin; i <= end; i++) {
                swap(a,begin,i);
                pailie(a, begin+1, end);
                swap(a, begin, i);
            }
        }
    }

    private void swap(int[] a, int i, int j) {
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值