回溯法

批处理作业调度-回溯法

匿名 (未验证) 提交于 2019-12-02 23:43:01
2019独角兽企业重金招聘Python工程师标准>>> 问题描述:   给定n个作业,集合J=(J1,J2,J3)。每一个作业Ji都有两项任务分别在2台机器上完成。每个作业必须先有机器1处理,然后再由机器2处理。作业Ji需要机器j的处理时间为tji。对于一个确定的作业调度,设Fji是作业i在机器j上完成处理时间。则所有作业在机器2上完成处理时间和f=F2i,称为该作业调度的完成时间和。 简单描述:   对于给定的n个作业,指定最佳作业调度方案,使其完成时间和达到最小。 算法设计:   从n个作业中找出有最小完成时间和的作业调度,所以批处理作业调度问题的解空间是一棵排列树。   类Flowshop的数据成员记录解空间的结点信息,M输入作业时间,bestf记录当前最小完成时间和,bestx记录相应的当前最佳作业调度。   在递归函数Backtrack中,      当i>n时,算法搜索至叶子结点,得到一个新的作业调度方案。此时算法适时更新当前最优值和相应的当前最佳调度。     当i<n时,当前扩展结点在i-1层,以深度优先方式,递归的对相应子树进行搜索,对不满足上界约束的结点,则剪去相应的子树。 算法描述: class Flowshop { friend Flow ( int * *, int , int []); private : void Backtrack ( int i )

装载问题-回溯法

匿名 (未验证) 提交于 2019-12-02 23:43:01
2019独角兽企业重金招聘Python工程师标准>>> 问题描述:   有一批共n个集装箱要装上2艘载重量分别为c1和c2的轮船,其中集装箱i的重量是wi,且不能超。 算法思想:   最优装载方案: 将第一艘轮船尽可能的装满;  然后将剩余的装载第二艘船上 算法描述: template < class Type > class Loading { friend Type MaxLoading ( Type [], Type , int ); private : void Backtrack ( int i ); int n ; Type * w , c , cw , bestw ; }; template < class Type > void Loading < Type >:: Backtrack ( int i ) { if ( i > n ) { if ( cw > bestw ) bestw = cw ; return ; } if ( cw + w [ i ] <= c ) { cw += w [ i ]; Backtrack ( i + 1 ); cw -= w [ i ]; } Backtrack ( i + 1 ); } template < class Type > Type MaxLoading ( Type w [], Type c , int n ) {

C++算法:括号生成----回溯法

匿名 (未验证) 提交于 2019-12-02 23:36:01
题目: 给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合。 例如, 给出 n = 3,生成结果为:["((()))","(()())", “(())()”, “()(())”, “()()()”] 思路: 方法一:暴力法 思路: 因为最后的结果必然是2n长度的字符串!!! 我们可以生成所有 2^{2n}个 ‘(’ 和 ‘)’ 字符构成的序列。然后,我们将检查每一个是否有效。 算法: 为了生成所有序列,我们使用递归。长度为 n 的序列就是 ‘(’ 加上所有长度为 n-1 的序列,以及 ‘)’ 加上所有长度为 n-1 的序列。 为了检查序列是否为有效的,我们会跟踪 平衡,也就是左括号的数量减去右括号的数量的净值。如果这个值始终小于零或者不以零结束,该序列就是无效的,否则它是有效的。 方法二:回溯法 思路和算法: 每次判断左括号数<n,右括号数<左括号数!!! 只有在我们知道序列仍然保持有效时才添加 ‘(’ or ‘)’,而不是像 方法一 那样每次添加。我们可以通过跟踪到目前为止放置的左括号和右括号的数目来做到这一点, 如果我们还剩一个位置,我们可以开始放一个左括号。 如果它不超过左括号的数量,我们可以放一个右括号。 方法三:闭合数 ˼· 为了枚举某些内容,我们通常希望将其表示为更容易计算的不相交子集的总和。 考虑有效括号序列 S 的 闭包数

全排列(回溯法与next_permutation)

匿名 (未验证) 提交于 2019-12-02 23:26:52
版权声明:即使允许了也不得转载 https://blog.csdn.net/weixin_43213056/article/details/88756200 深度搜索模板的套路: 先判断是否达到目标状态 如果达到,判断当前状态是否合法是否计入答案。 未达到,枚举可能的状态,记录本轮选择,进入下一层。 返回后,消除影响。 全排列(DFS) #include <iostream> using namespace std ; int n , a [ 100 ], vis [ 100 ], t ; void dfs ( int cur ) { if ( cur == n + 1 ) { for ( int k = 1 ; k <= n ; k ++) cout << a [ k ]; cout << endl ; t ++; return ; } else { for ( int i = 1 ; i <= n ; i ++) { if ( vis [ i ] == 0 ) { a [ cur ] = i ; vis [ i ] = 1 ; dfs ( cur + 1 ); vis [ i ] = 0 ; } } } } int main () { cin >> n ; dfs ( 1 ); cout << "Total=" << t ; return 0 ; } 运行结果: next

回溯法(深度优先法)速解

匿名 (未验证) 提交于 2019-12-02 23:06:17
算法解题部件: 根据问题定义解空间,这可以类似于概率论中的样本空间S,空间中包含所有的可能结果,多以n叉树实现; 约束条件,对解空间中的解做出约束,以缩减搜索解空间成本,避免不必要的搜索; 界限条件,根据约束条件,我们可以找到问题的所有可行解,当需要求得最优解是,我们需要设置界限条件,即当满足该条件时,我们可能找到最优解。 当我们需要找到所有可行解的时候,则只需要设定约束函数即可,若要求最优解,就需要两条件同时上阵了! 下面我们以对简单的0-1背包问题为例,学习回溯法: 问题分析&算法设计 很明显,在n个宝物中选择几个宝物带走,即从集合S中选择一个子集,要求子集的总重量不超过W,而且价值最大 针对于S中的每一个宝物,只会存在“拿”(1)与“不拿”(0)的问题,由此,我们可以得出解空间为{x1,x2,x3.....xn},其中xi=0/1;不难看出,解空间中一共有2^n种可能解,我们可以将解空间定义为深度为n的二叉树)(取左为1,取右为0)。 约束条件: 搜索过程中,沿着拓展节点的左分支拓展,表示装入宝物。由此可知,我们在拓展时应该判断约束条件是否成立,成立则左,不成立则右。 在每个节点判断界限条件,若不成立,则该节点为死结点,无须向下搜索。 代码示例: #include <iostream> #include <string> #include <algorithm>

回溯法解决工作分配问题及分析

匿名 (未验证) 提交于 2019-12-02 23:03:14
1、实践题目 工作分配问题 2、问题描述 设有n件工作分配给n个人。将工作i分配给第j个人所需的费用为cij 。 设计一个算法,对于给定的工作费用,为每一个人都分配1 件不同的工作,并使总费用达到最小。 输入格式: 输入数据的第一行有1 个正整数n (1≤n≤20)。接下来的n行,每行n个数,表示工作费用。 输出格式: 将计算出的最小总费用输出到屏幕。 输入样例: 3 输出样例: 9 3、算法描述(包括解空间,画出测试样例的解空间树,剪枝(约束函数或限界函数)方法描述) (1)解空间 解空间为{x1,x2,x3,・・・・・・,xn},其中xi=1,2,3,4・・・,n,表示第i个人安排的工作号。 (2)解空间树: 以n=3为例,解空间树如下: (3)剪枝方法 (4)具体代码 1 #include<iostream> 2 using namespace std; 3 #define N 1000 4 int cost[N][N]; // 表示第i个人完成第j件工作需要的费用 5 int isC[N] = {0}; // 用于记录第n个工作是否完成,0表示未完成 6 int n; 7 int scost; // 表示总费用 8 9 void Backstrack(int i, int c) 10 { 11 if(c > scost) return; 12 if(i == n) { //

回溯法数独求解

匿名 (未验证) 提交于 2019-12-02 21:45:52
public class SoduTest { private int[][] sodu = { // 最难的 // {0,0,5,3,0,0,0,0,0}, // {8,0,0,0,0,0,0,2,0}, // {0,7,0,0,1,0,5,0,0}, // {4,0,0,0,0,5,3,0,0}, // {0,1,0,0,7,0,0,0,6}, // {0,0,3,2,0,0,0,8,0}, // {0,6,0,5,0,0,0,0,9}, // {0,0,4,0,0,0,0,3,0}, // {0,0,0,0,0,9,7,0,0} // 包含两个解的 {7,6,1,2,4,5,8,3,9}, {3,2,8,1,7,9,4,5,6}, {0,0,4,8,3,6,7,2,1}, {8,7,5,9,6,4,2,1,3}, {2,3,9,7,5,1,6,4,8}, {1,4,6,2,8,3,9,7,5}, {4,1,7,3,9,8,5,6,2}, {0,0,3,4,2,6,1,8,7}, {6,8,2,5,1,7,3,9,4} }; public static void main(String[] args) { long timeStart = System.currentTimeMillis(); new SoduTest().getSoduAnswer(0, 0); long

n皇后问题(回溯法)——Python实现

你说的曾经没有我的故事 提交于 2019-12-01 17:36:20
八皇后问题 问题: 国际象棋棋盘是8 * 8的方格,每个方格里放一个棋子。皇后这种棋子可以攻击同一行或者同一列或者斜线(左上左下右上右下四个方向)上的棋子。在一个棋盘上如果要放八个皇后,使得她们互相之间不能攻击(即任意两两之间都不同行不同列不同斜线),求出一种(进一步的)布局方式。 【来源: https://www.cnblogs.com/franknihao/p/9416145.html 】具体讲解与实现 1 def check(board,row,col): 2 i = 0 3 while i < row: 4 if abs(col-board[i]) in (0,abs(row-i)): 5 return False 6 i += 1 7 return True 1 def EightQueen(board,row): 2 blen = len(board) 3 if row == blen: 4 print(board) 5 return True 6 col = 0 7 while col < blen: 8 if check(board,row,col): 9 board[row] = col 10 if EightQueen(board,row+1): 11 return True 12 col += 1 13 return False 1 def

回溯法--全排列

这一生的挚爱 提交于 2019-12-01 17:23:35
a=[1,2,3] n=len(a) res=[] def permutation(a,solution): #注意,这里要用global修饰res,才能更新结果 global res if len(a)==0: res.append(solution) return for i in range(len(a)):     newsolution=solution+[a[i]] new_a=a[:i]+a[i+1:] permutation(new_a,newsolution) permutation(a,[]) print(res) 输出: [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]] 基本思路: 其实对于回溯法,我们要从反向开始考虑。我们每次从原始数组中选择一个加入到结果中,当原始数组中(新建的)没有元素时(也就是len(a)==0,此时结果为[1,2,3]),我们得到了第一个排列,我们将这个排列加入到结果集中,然后返回上一步,也就是我们现在有[1,2],再返回一步[1],此时再加入3,再加入2,得到[1,3,2], 以此类推。 来源: https://www.cnblogs.com/xiximayou/p/11695640.html

回溯法实现求解子集合和问题

瘦欲@ 提交于 2019-11-30 16:44:00
1.回溯法简介 回溯法是一种在解空间搜索问题的解的方法。它在问题的解空间树种,按 深度优先 的策略,从根节点出发搜索解空间树。算法搜索至解空间树的任一节点时,先判断该节点是否包含问题的解。如果不包含,则跳过对以该节点为根的子树的搜索,逐层向其祖先节点回溯,否则进入该子树,继续按深度优先策略搜索。用回溯法求解问题的所有解的时,要回溯到根,且根节点的所有子树都被搜索遍才结束。用回溯法求问题的一个解时,只要搜索到问题的一个解就可以结束了,这种以深度优先方式系统搜索问题解的算法称为回溯法。 2.子集合和问题 3.代码 package depth.first.search; import java.util.Scanner; import java.util.Stack; /*** * 用深度优先算法求一个数组的子数组的和是否能达到某个值 * 回溯法 * @author admin * */ public class Subarray { public static void main(String[] args) { int n; Scanner in = new Scanner(System.in); n = in.nextInt(); int[] array = new int[n]; for (int i = 0; i < array.length; i++) { array[i]