回溯算法

1.回溯算法是什么

回溯算法又称“穷举法”,是一种通用解题的方法。
解题框架:

void backtrack (int t)  
{  
    if (t>n) output(x); //叶子节点,输出结果,x是可行解  
    else  
       for i = 1 to k//当前节点的所有子节点  
        {  
            x[t]=value(i); //每个子节点的值赋值给x  
            //满足约束条件和限界条件  
          if (constraint(t)&&bound(t))   
          		//保存状态
                backtrack(t+1);  //递归下一层  
                //回溯
        }  
}

2.例题

解空间是子集树

package recall;

import java.util.Scanner;

/**
 * 问题描述 
 * 给定n中物品和一个揹包,揹包容量是C 物品i的重量是wi,
 * 物品i的价值是vi 问如何装物品,使得揹包内的总价值最大
 * @author Administrator
 *
 */
public class Test1
{
	public static int itemNum; // 物品总数
	public static int ItemTotalWeight; // 揹包总容量

	public static int[] w; // 各个物品的重量
	public static int[] v; // 各个物品的价值
	public static int[] x; // 记录当前物品的放入状态
	public static int currentWeight = 0; // 当前总重量
	public static int currentValue = 0; // 当前总价值

	public static int bestValue = 0; // 最大价值
	public static int[] bestItems; // 存放最大价值的各个物品 1表示放入,0表示不放入

	public static void backTrack(int t)
	{

		// 到达遍历临界条件,遍历到叶子
		if (t > itemNum - 1)
		{
			// 保存最优解
			if (currentValue > bestValue)
			{
				bestValue = currentValue;
				System.arraycopy(x, 0, bestItems, 0, x.length);
			}
		} else
		{
			// 对每个物品进行遍历,只有0,1
			for (int i = 0; i <= 1; i++)
			{
				// 第t个物品进行 i状态
				x[t] = i;
				if (i == 0)
				{ // 不放入状态,则对下个物品进行
					backTrack(t + 1);
				} else
				{ // 放入状态,对约束条件进行判断
					if (currentWeight + w[t] <= ItemTotalWeight)
					{ // 可以放得下,保存状态
						currentValue += v[t];
						currentWeight += w[t];
						backTrack(t + 1);
						// 回到没放入之前的状态
						currentValue -= v[t];
						currentWeight -= w[t];
					}
				}
			}
		}
	}

	public static void main(String[] args)
	{
		Scanner scanner = new Scanner(System.in);
		while (true)
		{
			System.out.println("请输入有几种物品:");
			itemNum = scanner.nextInt();
			System.out.println("请输入揹包容量:");
			ItemTotalWeight = scanner.nextInt();
			w = new int[itemNum];
			v = new int[itemNum];
			x = new int[itemNum];
			bestItems = new int[itemNum];
			System.out.println("请输入各个物品的总量:");
			for (int i = 0; i < w.length; i++)
			{
				w[i] = scanner.nextInt();
			}
			System.out.println("请输入各个物品的价值:");
			for (int i = 0; i < v.length; i++)
			{
				v[i] = scanner.nextInt();
			}
			backTrack(0);
			System.out.println("最大价值:" + bestValue);
			for (int i = 0; i < bestItems.length; i++)
			{
				System.out.println("最优解:" + bestItems[i]);
			}
		}
	}

}

package recall;

import java.util.Scanner;
/**
 * 问题描述
 * 给定一个n阶迷宫,给定起始点,给定终点
 * 找出从起始点到终点的最短路径
 * @author Administrator
 *
 */
public class Test2
{
	public static int n=10;
	public static int state = 0 ; //0上 1下 2左 3右 
	public static int[][] map={
			
                {0,0,1,1,1,1,1,1,1,1}, //0  
                {1,0,0,1,1,0,0,1,0,1}, //1  
                {1,0,0,1,0,0,0,1,0,1}, //2  
                {1,0,0,0,0,1,1,0,0,1}, //3  
                {1,0,1,1,1,0,0,0,0,1}, //4  
                {1,0,0,0,1,0,0,0,0,1}, //5  
                {1,0,1,0,0,0,1,0,0,1}, //6  
                {1,0,1,1,1,0,1,1,0,1}, //7  
                {1,1,0,0,0,0,0,0,0,0}, //8  
                {1,1,1,1,1,1,1,1,1,0}  //9  
            //   0 1 2 3 4 5 6 7 8 9  
            };  
	
	public static int endX = 9;
	public static int endY = 9;
	public static int currentValue = 0;
	public static int[][] currentLoads = new int[10][10];
	public static int bestValue = 999;
	public static int[][] bestLoads = new int[10][10];
	public static void main(String[] args)
	{
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				currentLoads[i][j] = map[i][j]; 
			}
		}
		backTrace(0,0);
		System.out.println("最短路径:"+bestValue);
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				System.out.print(bestLoads[i][j]+" ");
			}
			System.out.println();
		}
		
	}
	private static void backTrace(int x, int y)
	{
		//到达终点
		if(x==endX && y==endY){
			currentValue++;
			currentLoads[x][y]=2;
			if(currentValue < bestValue){
				for(int i=0; i<n ;i++){
					for(int j=0;j<n;j++){
						bestLoads[i][j] = currentLoads[i][j]; 
					}
				}
				bestValue = currentValue;
			}
			
			currentValue--;
			currentLoads[x][y]=0;
		}
		else if(x>=n  || y>=n ||x< 0 || y< 0){
			//出界的路线
		}
		else{
			if(currentLoads[x][y]==0){
				currentLoads[x][y] = 2;
				currentValue++;
				backTrace(x, y+1);
				backTrace(x+1, y);
				backTrace(x, y-1);
				backTrace(x-1, y);
				currentValue--;
				currentLoads[x][y] = 0;
			}
		}
	}


}

解空间是排列树

package recall;

import java.io.OutputStream;
import java.util.Scanner;
/**
 *给定一个整数n,要求列出1-n的全排列
 * @author Administrator
 *
 */
public class Test3
{
	public static int n;
	public static int[] flag;
	public static int[] value;
	public static int count=0;
	public static void main(String[] args)
	{
		Scanner scanner = new Scanner(System.in);
		n = scanner.nextInt();
		flag = new int[n];
		value = new int[n];
		backTrace(0);
		System.out.println(count);
	}
	private static void backTrace(int t)
	{
		//选完元素
		if(t > n-1){
			count++;
			for(int i=0;i<n;i++){
				System.out.print(value[i]+" ");
			}
			System.out.println();
		}else{
			for(int i=1;i<=n;i++){
				if(flag[i-1]==0){ //还没选过的元素
					value[t] = i;
					flag[i-1] = 1;
					backTrace(t+1);
					value[t] = 0;
					flag[i-1] = 0;
				}
			}
		}
	}

}

    原文作者:算法
    原文地址: https://www.twblogs.net/a/5bddcc0f2b717720b51ad3ad
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞