回溯算法

C++搜索与回溯算法之红与黑

浪尽此生 提交于 2019-12-04 05:09:53
红与黑 Description 有一间长方形的房子,地上铺了红色、黑色两种颜色的正方形瓷砖。你站在其中一块黑色的瓷砖上,只能向相邻的黑色瓷砖移动。请写一个程序,计算你总共能够到达多少块黑色的瓷砖。 Input 包括多个数据集合。每个数据集合的第一行是两个整数W和H,分别表示x方向和y方向瓷砖的数量。W和H都不超过20。在接下来的H行中,每行包括W个字符。每个字符表示一块瓷砖的颜色,规则如下 1)‘.’:黑色的瓷砖; 2)‘#’:白色的瓷砖; 3)‘@’:黑色的瓷砖,并且你站在这块瓷砖上。该字符在每个数据集合中唯一出现一次。 当在一行中读入的是两个零时,表示输入结束。 Output 对每个数据集合,分别输出一行,显示你从初始位置出发能到达的瓷砖数(记数时包括初始位置的瓷砖)。 Sample Input 6 9 ....#. .....# ...... ...... ...... ...... ...... #@...# .#..#. 0 0 Sample Output 45 这道题我做了很久,主要原因就是卡在输入上了,后来才发现: 它是输入x轴、y轴(即先输入列数,后输入行数)! 它是输入x轴、y轴(即先输入列数,后输入行数)! 它是输入x轴、y轴(即先输入列数,后输入行数)! 重要的事情说三遍。 代码如下: #include<cstdio> #include<cstring>

洛谷P3943 星空——题解

不羁的心 提交于 2019-12-03 15:00:51
差分数组及树上差分 所谓差分,就是记录当前的元素与之前元素逻辑上的差距。   最基础的用法是差的差分数组:    记录当前位置的数与上一位置的数的差值。      即b[i]=a[i]-a[i-1] (b为差分数组,a为原数组)    通过对差分数组求前缀和,可以求出原数组,即:           甚至可以求出前缀和:          (s为原数组,sum为原数组的前缀和数组,b为差分数组)   可以O(1)优化区间加法:给原数组区间[l,r]的数都加上x,只要在b l处加x,b r+1 处减x。       有两种理解角度:         1、从差分定义出发,区间加x使区间左端点与它在原数组上一个数的差距加大了x、使区间右端点的后一个数与区间右端点的数的差距缩小了x,而没有改变区间中相邻2数的差距。         2、从差分数组的修改对原数组的影响入手:由于差分数组求前缀和得出原数组,当b l加x之后求前缀和,那么原数组自l及以后的数全部比b l加x之前多了x;同理当b r+1减x之后求前缀和,那么原数组自r+1及以后的数全部比b r+1减x之前少了x。总的一看,发现原数组l~r的部分就多了x,其余部分没有变化。      广义差分:差分维护的是相邻元素间的逻辑关系,从而使能从初始状态(a[0])通过差分数组表达的逻辑关系推出某个位置上a的值(从形式上看就是求前缀)

Leetcode题目46.全排列(回溯+深度优先遍历+状态重置-中等)

回眸只為那壹抹淺笑 提交于 2019-12-03 10:27:06
题目描述: 给定一个没有重复数字的序列,返回其所有可能的全排列。 示例: 输入: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ] 题目解析:来自leetcode@ liweiwei1419 以示例输入: [1, 2, 3] 为例,如果让我们手写,要做到不重不漏,我们书写的策略可能是这样:“一位一位确定”,这样说比较笼统,具体是这样的: 1、先写以 1 开始的两个排列:[1, 2, 3]、[1, 3, 2]; 2、再写以 2 开始的两个排列:[2, 1, 3]、[2, 3, 1]; 3、最后写以 3 开始的两个排列:[3, 1, 2]、[3, 2, 1]。 如果数组元素多一点的话,也不怕,我们写的时候遵循下面的原则即可: 1、按数组的顺序来(不要求排序,但我们选取元素的顺序是从左到右的),每次排定 1 个元素; 说明:只有按照顺序才能做到不重不漏。 2、新排定的元素一定不能在之前排定的元素中出现。 说明:如果违反了这一条,就不符合“全排列”的定义。 其实让程序帮你找到所有的全排列也是这样的思路。如果不是这样的话,我们要写数组长度这么多层的循环,编码极其困难,代码写出来也非常不好看。 这道题可以作为理解“回溯算法”的入门题。这是一个非常典型的使用 回溯算法 解决的问题。解决回溯问题,我的经验是

串的两种模式匹配方式(BF/KMP算法)

╄→гoц情女王★ 提交于 2019-12-03 09:55:23
前言 串,又称作字符串,它是由0个或者多个字符所组成的有限序列,串同样可以采用顺序存储和链式存储两种方式进行存储,在主串中查找定位子串问题(模式匹配)是串中最重要的操作之一,而不同的算法实现有着不同的效率,我们今天就来对比学习串的两种模式匹配方式: 朴素的模式匹配算法(Brute-Force算法,简称BF算法) KMP模式匹配算法 朴素的模式匹配算法(BF算法) BF算法是模式匹配中的一种常规算法,它的思想就是: 第一轮 :子串中的第一个字符与主串中的第一个字符进行比较 若相等 ,则继续比较主串与子串的第二个字符 若不相等 ,进行第二轮比较 第二轮 :子串中的第一个字符与主串中第二个字符进行比较...... 第N轮 :依次比较下去,直到全部匹配 图示说明: 第一轮: 第二轮: ...... 原理一致,省略中间步骤 第五轮: 第六轮: 代码实现: 看完文字与图例讲解,我们来动手实现一个这样的算法 简单归纳上面的步骤就是: 主串的每一个字符与子串的开头进行匹配,匹配成功则比较子串与主串的下一位是否匹配,匹配失败则比较子串与主串的下一位,很显然,我们可以使用两个指针来分别指向主串和子串的某个字符,来实现这样一种算法 匹配成功,返回子串在主串中第一次出现的位置,匹配失败返回 -1,子串是空串返回 0 int String::bfFind(const String &s, int pos)

JAVA数据结构和算法 6 递归

老子叫甜甜 提交于 2019-12-03 02:11:29
递归:直接或者间接地调用自己。比如计算连续数的阶乘,计算规律:n!=(n-1)!*n。 每个递归方法都有一个基值(终止)条件,以防止无线地递归下去,以及由此引发的程序崩溃。 采用递归是因为它可以从概念上简化问题,递归算法结构清晰、可读性强,且容易采用数学归纳法证明算法正确性。然而时间花费和空间花费都比非递归算法更大。 关于递归与分治: 分治法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题与原问题相同且相互独立。 递归地解这些子问题 ,然后将各子问题的解合并得到原问题的解。 使用分治思想设计出的算法一般是递归算法, 所以分治问题的时间复杂度也可以用递归方程来分析 。 关于递归与回溯: 回溯也是一种算法思想,可以用递归实现。通俗点讲回溯就是一种试探,类似于穷举,但回溯有“剪枝”功能。 来源: https://www.cnblogs.com/lsh0908/p/11770783.html

回溯算法――0-1背包

匿名 (未验证) 提交于 2019-12-02 23:55:01
回溯算法的思想:每到一个十字路口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

20191030-带返回值的回溯算法Leetcode解数独

巧了我就是萌 提交于 2019-12-02 23:53:44
题目描述 编写一个程序,通过已填充的空格来解决数独问题。 一个数独的解法需遵循如下规则: 数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。 空白格用 '.' 表示。 一个数独。 答案被标成红色。 Note: 给定的数独序列只包含数字 1-9 和字符 '.' 。 你可以假设给定的数独只有唯一解。 给定数独永远是 9x9 形式的。 输入格式: [["5","3",".",".","7",".",".",".","."],["6",".",".","1","9","5",".",".","."],[".","9","8",".",".",".",".","6","."],["8",".",".",".","6",".",".",".","3"],["4",".",".","8",".","3",".",".","1"],["7",".",".",".","2",".",".",".","6"],[".","6",".",".",".",".","2","8","."],[".",".",".","4","1","9",".",".","5"],[".",".",".",".","8",".",".","7","9"]] 输出格式: [['5', '3', '4', '6', '7', '8',

深度优先算法回溯实例

匿名 (未验证) 提交于 2019-12-02 23:38:02
将1-9九个数字不重复填入口口口口x口=口口口口中使等式成立,写出所有的情况 #include <stdio.h> int num[10]={0}; //记录每个位置上的数字 int status[10]={0}; //记录1-9的状态,用过记为1 void dfs(int dep) { if(dep == 10) //当到第9步的时候检测值是否满足,判断放在前面所以要10 { if((num[1]*1000+num[2]*100+num[3]*10+num[4])*num[5]==(num[6]*1000+num[7]*100+num[8]*10+num[9])) printf("%d%d%d%d * %d = %d%d%d%d\n",num[1],num[2],num[3],num[4],num[5],num[6],num[7],num[8],num[9]); return ; } for(int i = 1; i < 10; i++) //循环当前位置剩余的所有数字 { if(!status[i]) { num[dep] = i; status[i] = 1; // 找到了就标记掉,继续下一层 dfs(dep + 1); //这里进行下一步dfs status[i] = 0; //回溯思想用完了一个数字后,把标记还原 } } } int main() { dfs(1); }

0-1背包回溯算法【适合小白,带分析+注释】

匿名 (未验证) 提交于 2019-12-02 23:34:01
0-1背包回溯算法【适合小白,带分析+注释】 题目:用回溯算法实现0-1背包,背包的容积为7 装4件物品,物品的价值分别9,10,7,4,物品的重量分别是3,5,2,1,请用回溯法实现背包所能装入的最大价值? 分析: 所谓0-1背包,为了最大的价值,考虑当前物品装或者不装【只有这两种情况,而背包问题可以只装物品的部分】,解空间可以用子集数来表示。 解0-1背包问题的回溯法,与装载问题的回溯法类似,搜索解空间树时,只要左孩子结点是一个可行结点,搜索就进入左子树,而只有在右子树包含更优解时才进入右子树,否则就把右子树剪掉。 这就是问题的关键,怎么把右子树剪掉:我们可以设计一个上界函数,只有当上界函数返回的值大于当前最优值,才进入右子树(也就是说,当前这个物品我不装,而去装下一个物品,得到的价值更大) 上界函数:将物品按单位重量价值降序排列,依次取物品装入【这是为了得到一个上界值,其实本身是不能取到的,所以当物品放不下,我们可以取部分装,这就类似背包问题】 所以物品的价值,重量,单位价值属性用结构体存储,本方法大部分处理时间在这个,其实回溯很简单,主要是为了oj提交,直接根据题目所给的数据进行编程,如果只是想练习回溯,可以自己事前计算好物品的单位重量价值,然后将价值数组,重量数组也按物品的单位重量价值降序排列 转载请标明出处: 0-1背包回溯算法【适合小白,带分析+注释】 文章来源:

KMP算法

主宰稳场 提交于 2019-12-02 21:59:15
KMP算法用于字符串匹配问题 原有一个主串T和一个要匹配字符串S 对S求next熟组然后进行较少回溯匹配 求next数组。也就是在S串匹配不正确时 进行回溯。 每个next数组指向前一个应该回溯对下标 然后进行匹配 对于每个不匹配字符串重新依据next数组匹配 来源: https://www.cnblogs.com/AAAzhuo/p/11764111.html