回溯算法

LeetCode解题汇总目录

a 夏天 提交于 2019-12-02 17:37:52
此篇为学习完 《数据结构与算法之美》 后,在 LeetCode 刷题的汇总目录,方便大家查找(Ctrl+F ind ),一起刷题,一起PK交流!Updated on 2019.12.2 刷题可以按照 不同的专题 进行,便于加强某个知识点的理解。 我的 LeetCode 主页 我的 GitHub 主页 已解决 519/1185 - 简单 281 中等 208 困难 30 2019.7.24 - 2019.11.9,108天做了400道题 2019.11.9 - 2019.11.24, AC+100道,4个月共计500道题 参赛记录 LeetCode 2019 力扣杯全国秋季编程大赛 ​ 已解题目,部分太简单的没有列出 LeetCode 1. 两数之和(哈希) LeetCode 2. 两数相加(单链表反转) LeetCode 3. 无重复字符的最长子串(滑动窗口+哈希) LeetCode 4. 寻找两个有序数组的中位数(二分查找,难) LeetCode 7. 整数反转 LeetCode 8. 字符串转换整数 (atoi) LeetCode 9. 回文数 LeetCode 11. 盛最多水的容器(双指针) LeetCode 14. 最长公共前缀 LeetCode 15. 三数之和 LeetCode 16. 最接近的三数之和(固定左端+滑动窗口) LeetCode 17.

回溯,爆搜 刷题记录

故事扮演 提交于 2019-12-02 15:42:33
算法只会暴力 HDU 5952 Counting Cliques 一个图,求大小为s的完全图的个数 每个完全图都给遍历一次。。。d(u,c,x)为遍历到大小为c的完全图(此时该完全图上的点都存在数组x里),然后u是此时该完全图上的点里最大的那个点 这样是为了每个完全图都只遍历一次,因为一定是按照编号从小到大遍历的 每次考察u的所有直连的点(只有这些点有可能和上面的图形成完全图),然后判断这个点是不是可以和上面的图形成完全图 时间复杂度就是所有大小为s的完全图的个数*20,其中可以优化的地方就是后面那个20了。。。但是我又懒又傻所以过了就行了。。。 代码: 1 #include <bits/stdc++.h> 2 #define nmax 110 3 4 using namespace std; 5 int cas,n,M,s,ans; 6 vector <int> g[nmax]; 7 int m[nmax][nmax]={0}; 8 9 inline void init(){ 10 memset(m,0,sizeof(m)); 11 for (int i=0; i<=n; i++) g[i].clear(); 12 ans=0; 13 } 14 15 inline void dfs(int u,int c,int* x){ //当前遍历了c个,其中最大的是u 16 if(c==s

八皇后,回溯与递归(Python实现)

柔情痞子 提交于 2019-12-02 15:05:08
八皇后,回溯与递归(Python实现) 八皇后问题是十九世纪著名的数学家高斯1850年提出 。以下为python语言的八皇后代码,摘自《Python基础教程》,代码相对于其他语言,来得短小且一次性可以打印出92种结果。同时可以扩展为九皇后,十皇后问题。 问题:在一个 8*8 棋盘上,每一行放置一个皇后旗子,且它们不冲突。冲突定义:同一列不能有两个皇后,每一个对角线也不能有两个皇后。当然,三个皇后也是不行的,四个也是不行的,凭你的智商应该可以理解吧。 解决方案:回溯与递归。 介绍: 1.回溯法 回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为“回溯点”。参见 百度百科 2.递归法 阶乘 n! = 1 x 2 x 3 x ... x n 用函数 fact(n) 表示,可以看出: fact(1) = 1 fact(n) = n! = 1 x 2 x 3 x ... x (n-1) x n = (n-1)! x n = fact(n-1) x n 于是, fact(n) 用递归的方式写出来就是: def fact(n): if n==1: return 1 return n * fact(n - 1) 如果计算 fact(5) ,结果如下: ==

字符串模式匹配——KMP算法

核能气质少年 提交于 2019-12-01 16:53:10
KMP算法匹配字符串 朴素匹配算法   字符串的模式匹配的方法刚开始是朴素匹配算法,也就是经常说的暴力匹配,说白了就是用子串去和父串一个一个匹配,从父串的第一个字符开始匹配,如果匹配到某一个失配了,就重新去从父串的下一个字符开始匹配,这样的算法虽然理解起来容易,但是算法的时间复杂度无疑是很高的,假如父串是一个很长的字符串,而字串恰恰不和父串匹配,那无疑是对CPU的迫害。   下面贴几张图看看这种朴素匹配算法: 但是第四个出现失配,就得重新让字串去和父串的第二个字符匹配,发现第二个也不匹配,只能再次匹配第三个,如下:   这样下来时间复杂度大大变高,但是通过上帝视角我们可以发现其实第二个完全不用试,但是计算机不知道啊,所以我们就需要一个更好的算法来解决这个问题,这个算法就是要在朴素算法的基础上额外告诉计算机哪些地方不用尝试,可能我上面的这个例子举得不太恰当,但是这个算法的额外功能就是告诉了计算机如果某个位置失配了应该去尝试哪个位置。    KMP算法——和计算机的友好交流   前面我们说KMP算法其实就是告诉计算机如果某个位置失配后应该往哪个位置回溯。而这个功能的实现其实只需要一个next数组,而这个数组也恰恰是这个算法的核心所在。 next数组   这个数组里面存储的就是字串中每个位置失配后应该回溯的下标。举个例子,比如第9个元素失配后应该回溯到第3个再次匹配尝试

回溯算法批处理作业调度问题

五迷三道 提交于 2019-11-30 01:48:09
1、问题描述 给定n个作业的集合J={j1,j2,j3,…jn},每一个作业都有两项任务分别在两台机器上完成。每个作业必须先由机器1处理,再由机器2处理。作业Ji需要机器j的处理时间为tij,设Fij是作业i在机器j上的完成处理时间。所有作业在机器2上处理的时间和称为该作业调度的完成时间和。 批处理作业调度问题要求对于给定的N个作业,制定最佳作业调度方案,使其完成时间和达到最小。其中最典型的一个例子就是在计算机系统中完成一批n个作业,每个作业都先完成计算,然后将计算结果打印出来。 示例: tji 机器1 机器2 作业1 2 1 作业2 3 1 作业3 2 3 在这个例子中。最优调度顺序为:1 3 2;处理时间为:18 2、算法描述 从n个作业的所有排列中找出有最小完成时间和的作业调度,所以批处理调度问题是一颗排列树按照回溯搜索排列树的算法框架,设开始时x=[1,2,3,4…,n]是所给的n个作业,则相应的排列树由 x[1,n]的所有排列构成。 在递归方法backtrack中,当i>n时,算法搜索至叶结点,得到一个新的作业调度方案。此时算法适时更新当前最优值和相应的当前作业调度。 当i<n时,当前扩展结点位于排列树的第i-1层。此时算法选择下一个要安排的作业,以深度优先的方式递归的对相应字数进行搜索。对于不满足上届约束的结点,则减去相应的子树。 程序初始化: int x [ 100

递归,回溯算法两大经典案例—迷宫问题和八皇后问题

江枫思渺然 提交于 2019-11-29 20:02:22
迷宫问题: 问题描述: 用二维数组表示一个迷宫,比如1表示墙,0表示空格,设置一个起点和终点,让小球自己从迷宫的起点到终点走出一条路径,并将路径标识为2。 代码实现: 1 package cn.ftf.digui; 2 3 public class MiGong { 4 public static boolean findPath(int[][]arr,int i,int j) { 5 //结束条件 6 if(arr[6][5]==2) { 7 return true; 8 } 9 if(arr[i][j]==0) { 10 arr[i][j]=2; 11 if(findPath(arr,i+1,j)) { 12 return true; 13 }else if(findPath(arr,i,j+1)){ 14 return true; 15 }else if(findPath(arr,i-1,j)){ 16 return true; 17 }else if(findPath(arr,i,j-1)){ 18 return true; 19 }else { 20 arr[i][j]=3; 21 return false; 22 } 23 }else { 24 return false; 25 } 26 } 27 public static void main(String[]

搜索与回溯算法:八皇后问题

雨燕双飞 提交于 2019-11-29 18:22:22
1213:八皇后问题 时间限制: 1000 ms 内存限制: 65536 KB 提交数: 10320 通过数: 3609 【题目描述】 在国际象棋棋盘上放置八个皇后,要求每两个皇后之间不能直接吃掉对方。 【输入】 (无) 【输出】 按给定顺序和格式输出所有八皇后问题的解(见样例)。 【输入样例】 (无) 【输出样例】 No. 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 No. 2 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 ...以下省略 【来源】 i表示行,a[j]=i,表示第i行的第j个数 #include<iostream> using namespace std; int a[10001],b[10001],w[10001],m[10001],tot = 0; int print() { tot++; cout << "No. " << tot <<

数据结构(六)图

耗尽温柔 提交于 2019-11-29 14:20:48
术语 实现 算法 一、概述 存在对应关系就连边,邻接关系 顶点与顶点之间的关系 参与定义邻接关系的每个顶点,与这个邻接关系的关系称作关联关系 顶点与相关的某条边的关系 本章忽略下面这种边 无向图/有向图 所有边均无方向的图,即无向图undigrapy 反之,有向图digraph中均为有向边directed edge,u、v分别称作边(u, v)的尾(tail)、头(head) 混合图 路径/环路 有向无环图DAG,在有向图中不包含任何的环路 简单路径和简单环路,都不包含重复的点 欧拉环路,覆盖了图中所有的点 哈密尔顿环路,经过所有顶点,且只经过一次的环路 二、邻接矩阵 在计算机中如何以数据结构的方式实现图? Graph模板类 template <typename Tv, typename Te> class Graph { // 顶点类型、边类型 private: void reset() { // 所有顶点、边的辅助信息 for (int i = 0; i < n; i++) { // 顶点 status(i) = UNDISCOVERED; dTime(i) = fTime(i) = -1; parent(i) = -1; priority(i) = INT_MAX; for (int j = 0; j < n; j++) // 边 if (exists(i, j))

运动员最佳配对问题(回溯)

…衆ロ難τιáo~ 提交于 2019-11-29 00:44:04
羽毛球队有男女运动员各n人。给定2个n×n 矩阵P和Q。P[i][j]是男运动员i和女运动员 j配对组成混合双打的男运动员竞赛优势;Q[i][j]是女运动员i和男运动员j配合的女运动员竞赛优势;由于技术配合和心理状态等各种因素影响,P[i][j]不一定等于Q[j][i]。男运动员i和女运动员j配对组成混合双打的男女双方竞赛优势为P[i][j]* Q[j][i]。设计一个算法,计算男女运动员最佳配对法,使各组男女双方竞赛优势的总和达到最大。 算法设计:设计一个算法,计算男女运动员最佳配对法,使各组男女双方竞赛优势的总和达到最大。 数据输入:第一行有1个正整数n(1≦n≦20〉。接下来的2n行,每行n个数。前n行是p,后n行是 q。 结果输出:将计算的男女双方竞赛优势的总和的最大值输出到文件output.txt。 输入文件示例 输出文件示例 input.txt output.txt 3 52 10 2 3 2 3 4 3 4 5 2 2 2 3 5 3 4 5 1 算法思想:排列树问题,重新开辟一个数组记录女运动员或者男运动员,对其进行全排列,到回溯到最后一行时将得到的值与之前已得到的最大值进行比较,如果大于之前的最大值,则进行更新 参考代码如下: #include<stdio.h> #include<stdlib.h> #define N 100 int n; int P[N][N]

回溯算法——0-1背包

北城以北 提交于 2019-11-28 17:57:59
回溯算法的思想:每到一个十字路口A,就选择一条路走a,如果a走不通,则回到十字路口A,选择其他bcd之一,进行走。若依然走不通,则退回到A之前的十字路口,重复上面的操作。 利用回溯算法解决的经典问题:数独、八皇后、0-1背包、图的着色、旅行商问题、全排列等等。 0-1背包问题 #include<iostream> #define MAX_WEIGHT 100 using namespace std; // arr 待装包的物品重量, // curweight 当前i物品的重量 // i 当前即将放入的i物品 // num 可用物品的数量 // bagweight 当前背包的总重量 void fill(int *arr, int curweight, int i, int num, int &bagweight) { if(curweight == MAX_WEIGHT || i == num) // 装满,或者考察完所有物品 { if(curweight > bagweight) { bagweight = curweight; // 记录历史最大装载量 // cout << bagweight << "***" << endl << endl; } return; } fill(arr, curweight, i + 1, num, bagweight); // 不选择i物品