回溯法

又回到最初的起点!——回溯法总结

ぐ巨炮叔叔 提交于 2019-12-14 13:40:56
又回到最初的起点,通向未来的路不只一条 ——算法第五章总结 软三 杨伟耿 20181003083 一、 见招拆招,百试不爽 回溯法——“通用的解题法”,也就是系统地搜索一个问题的所有解或任一解,它是一个既带有系统性又带有跳跃性的搜素算法——深度搜索! 在我自己的认知下,回溯法的模板就像一棵树,然后不断选择每一层的结点,遇到不满足的条件就返回上一个结点选择别的数据作结点再继续。深度搜索,遍历所有解法,总会得到正解!短板:时间复杂度高!所以这时候就需要用到“约束函数”、“限界函数”来减少一些没必要和重复的工作。 二、 “子集和”问题 5-1 子集和问题 (25分) 设集合S={x1,x2,…,xn}是一个正整数集合,c是一个正整数,子集和问题判定是否存在S的一个子集S1,使S1中的元素之和为c。试设计一个解子集和问题的回溯法。 输入格式: 输入数据第1行有2个正整数n和c,n表示S的大小,c是子集和的目标值。接下来的1行中,有n个正整数,表示集合S中的元素。 是子集和的目标值。接下来的1 行中,有n个正整数,表示集合S中的元素。 输出格式: 输出子集和问题的解,以空格分隔,最后一个输出的后面有空格。当问题无解时,输出“No Solution!”。 输入样例: 在这里给出一组输入。例如: 5 10 2 2 6 5 4 输出样例: 在这里给出相应的输出。例如: 2 2 6 解空间结构

算法学步:回溯法-8皇后问题

十年热恋 提交于 2019-12-11 20:41:36
问题描述: 有八个皇后(可以当成八个棋子),如何在 8*8 的棋盘中放置八个皇后,使得任意两个皇后都不在同一条横线、纵线或者斜线上 做法: 从第一行开始,一行一行地考虑,这样起码可以保证皇后不在同一行; 考虑下面的每一行的时候,需要让新增加的棋子不在前面添加的棋子的左下、正下、右下,即新增加的棋子的列不等于前面棋子的列,它的行号+列号不等于前面棋子的行号加列号(不在左下),|行号-列号|不等于之前棋子的|行号-列号|(不在右下); 如果该行所有位置都不符合要求,则回溯到前一行,改变皇后的位置,继续试探; 如果试探到最后一行,所有皇后摆放完毕,则直接打印出 8*8 的棋盘。最后一定要记得将棋盘恢复原样,避免影响下一次摆放。 程序代码: /*回溯法,8皇后问题*/ #include<stdio.h> #include<iostream> #include<cmath> #include<math.h> using namespace std; int weizhi[8]={0};//用来保存八个棋子的位置 int counts=0; bool check(int hang, int lie); void Queens(int nhang); void print(); int main() { Queens(0); cout<<"8皇后问题的解的个数为:"<<counts<<endl;

暴力回溯法 解八皇后

 ̄綄美尐妖づ 提交于 2019-12-11 03:45:41
国际象棋 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 public class _8Queen { //回溯法,暴力解8皇后 private static int ways = 0; //返回解法个数 public static int f8queen() { int[][] board = new int[8][8]; ways = 0; p_f8queen(board, 0); return ways; } private static void p_f8queen(int[][] board, int row) { if (row > 7) { ways++; printBoard(board); //最后一行穷举完,输出棋盘 return; } for (int col = 0; col < 8; col++) { if (check(board, row, col)) { //检测是否符合规则 board[row][col] = 1; //放皇后棋子 p_f8queen(board, row + 1);//进入下一行 board[row][col] = 0; //清除 } } }

回溯法

不问归期 提交于 2019-12-09 22:30:56
N皇后问题 递归: #include<iostream> #include<vector> #include<stack> #include<cmath> #include<cstring> using namespace std; typedef pair<int, int> P; int n,sum; vector<P> v; bool judge(int x, int y){ for (int i = 0; i < v.size(); i++){ float bioas = (v[i].second*1.0 - y*1.0) / (v[i].first*1.0 - x * 1.0); if (x == v[i].first || y == v[i].second || abs(bioas) == 1.0) return false; } return true; } void trace(int index){ if (index >= n){ sum++; for (int i = 0; i < v.size(); i++) printf("(%d, %d) ", v[i].first, v[i].second); cout << endl; return; } for (int i = 0; i < n; i++){ if (judge(index, i)){ v

回溯法算0-1背包

放肆的年华 提交于 2019-12-09 21:17:41
# include <stdio.h> //#include <conio.h> # include <fstream> # include <iostream> # include <stdlib.h> # define N 6 //物品数量 # define M 3 using namespace std ; double dataArr [ N * M + 1 ] ; double c ; //背包容量 double v [ N + 1 ] ; //各个物品的价值 double w [ N + 1 ] ; //各个物品的重量 double cw = 0.0 ; //当前背包重量 double cp = 0.0 ; //当前背包中物品价值 double bestp = 0.0 ; //当前最优价值 int order [ N + 1 ] ; int put [ N + 1 ] ; //设置是否装入 int ans [ N + 1 ] = { 0 } ; double perp [ N + 1 ] ; void knapsack ( ) { int i , j ; int temporder = 0 ; double temp = 0.0 ; for ( i = 1 ; i <= N ; i ++ ) perp [ i ] = v [ i ] / w [ i ] ; for (

算法设计与分析——回溯法算法模板

痴心易碎 提交于 2019-12-09 20:13:41
以深度优先方式系统搜索问题解的算法称为回溯法。在回溯法中,解空间树主要分为了四种子集树、排列树、n叉树和不确定树。 在《算法设计与分析课本》中介绍了11个回溯法的问题样例,这里根据解空间树的类型做一个分类。 子集树 装载问题 符号三角形问题 0-1背包问题 最大团问题 算法模板: void backtrack(int t) { if(搜索到叶子结点) { return; } for(i=0; i<=1; i++) //01二叉树 { if(满足约束函数和限界函数)//剪枝 { backtrack(t+1); } } } 排列树 批处理作业调度 旅行售货员问题 圆排列问题 电路板排列问题 算法模板: void backtrack(int t) { if(搜索到叶子结点) { return; } for(i=0; i<=n; i++) { if(满足约束函数和限界函数)//剪枝 { swap(x[t],x[i]); backtrack(t+1); swap(x[t],x[i]); } } } n叉树 n后问题 图的m着色问题 算法模板: void backtrack(int t) { if(搜索到叶子结点) { return; } for(i=1; i<=n; i++) //n叉树 { x[t]=i;//例如n后问题中,记录第t后所在的第i列 if(满足约束函数和限界函数)//剪枝 {

01背包问题(回溯法实现,java)

℡╲_俬逩灬. 提交于 2019-12-08 11:29:26
上两天学习的回溯算法,老师让我们回溯法来解决01背包问题, 经过了几天的改改增增,终于实现成功了。 自我感觉回溯算法思想,从左到右,一步一步,能走则走,不能则过! 下面直接贴代码,代码上详细注释! import java.util.Arrays; /** * 回溯法的01背包 * * @author anLA * */ public class BagFBack { private MyElement[] myelements; // 封装的物品 private float s; // 背包容量 private float nowWeight = 0; // 记录当前以拿重量 private float nowPrice = 0; // 记录当前以拿价格 private float betterValue; // 记录最多的价格 /* * 构造方法,用于初始化各个变量 */ public BagFBack(float[] w, float[] v, float s) { myelements = new MyElement[w.length]; for (int i = 0; i < w.length; i++) { myelements[i] = new MyElement(); myelements[i].v = v[i]; myelements[i].w = w[i]; }

回溯法解01背包问题

狂风中的少年 提交于 2019-12-08 11:27:04
关于回溯法的概念,这篇文章讲的比较通俗易懂: https://blog.csdn.net/jarvischu/article/details/16067319 贴出阅读这篇文章后解决01背包问题的Java代码,注释中加入了自己的理解 package com.zxg.algorithm.backtrack; /** * 回溯法解01背包问题 * 背包问题的概念不再赘述。这里主要讲解下回溯法思路。 * 将每一个物品分为装载和不装载两条路径,一个接一个的遍历,每遍历一个物品就会产生两条分支 * 那么就会组成一棵树,深度遍历这棵树,找出最优解 * 参考:https://blog.csdn.net/jarvischu/article/details/16067319 */ public class PackageQuestion { public int[] weight; public int[] value; public int[] take; int curWeight = 0; int curValue = 0; int bestValue = 0; int[] bestChoice; int count; int maxWeight = 0; public void init(int[] weight, int[] value, int maxWeight) { if

【算法分析】回溯法解八皇后问题(n皇后问题)

有些话、适合烂在心里 提交于 2019-12-07 04:48:06
回溯法解题思路: (1)针对所给问题,定义问题的解空间;    (2)确定易于搜索的解空间结构;    (3)以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。 八皇后问题: 八皇后问题,是一个古老而著名的问题,是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯·贝瑟尔于1848年提出:在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。 图解回溯法解八皇后问题: 回溯法解N皇后问题 1 、使用一个一维数组表示皇后的位置, 其中数组的下标表示皇后所在的行, 数组元素的值表示皇后所在的列。 2 、假设前n- 1 行的皇后已经按照规则排列好, 那么可以使用回溯法逐个试出第n行皇后的合法位置, 所有皇后的初始位置都是第 0 列, 那么逐个尝试就是从 0 试到 N - 1 , 如果达到 N ,仍未找到合法位置, 那么就置当前行的皇后的位置为初始位置 0 , 然后回退一行,且该行的皇后的位置加 1 ,继续尝试, 如果目前处于第 0 行,还要再回退,说明此问题已再无解。 3 、如果当前行的皇后的位置还是在 0 到 N - 1 的合法范围内, 那么首先要判断该行的皇后是否与前几行的皇后互相冲突, 如果冲突,该行的皇后的位置加 1 ,继续尝试, 如果不冲突,判断下一行的皇后, 如果已经是最后一行,说明已经找到一个解

算法设计基本方法

和自甴很熟 提交于 2019-12-06 12:48:42
1.1.2 算法设计基本方法 计算机解题的过程实际上是在实施某种算法,这种算法称为计算机算法。 常用算法设计方法: (1) 列举法 列举法的基本思想是,根据提出的问题,列举所有可能的情况,并用问题中给定的条件检验哪些是需要的,哪些是不需要的。 列举法的特点是算法比较简单。但当列举的可能情况较多时,执行列举算法的工作量将会很大。 在用列举法设计算法时,使方案优化,尽量减少运算工作量,是应该重点注意的。 在设计列举算法时,只要对实际问题进行详细的分析,将与问题有关的知识条理化、完备化、系统化,从中找出规律;或对 所有可能的情况进行分类,引出一些有用的信息,是可以大大减少列举量的。 列举算法是计算机算法中的一个基础算法。 (2) 归纳法 归纳法的基本思想是,通过列举少量的特殊情况,经过分析,最后找出一般的关系。 归纳就是通过观察一些简单而特殊的情况,最后总结出一般性的结论。 (3) 递推 所谓递推,是指从已知的初始条件出发,逐次推出所要求的各中间结果和最后结果。 其中初始条件或是问题本身已经给定,或是通过对问题的分析与化简而确定。 递推关系式往往是归纳的结果。 (4) 递归 人们在解决一些复杂问题时,为了降低问题的复杂程度(如问题的规模等),一般总是将问题逐层分解,最后归结为一些最简单 的问题。这种将问题逐层分解的过程,实际上并没有对问题进行求解,而只是当解决了最后那些最简单的问题后