分治算法

算法第三章作业

天涯浪子 提交于 2019-12-03 08:18:17
1. 你对动态规划算法的理解 动态规划的实质是分治思想和解决冗余,他与贪心和分治法类似,它们都将问题分为更小的类似的子问题。但贪心算法可能不能得到全局最优解,动态规划可以处理不具有贪心实质的问题。 2. 分别列出编程题1、2的递归方程 (1. f[i] = max{ f[k] | a[k] < a[i] } (1<=k<i) (2. f[i] = min{ f[k] + a[i][k] } (i<k<=j) 3. 说明结对编程情况 我和队友会先自己思索一段时间,其中一人敲另一个看,其间会有相互提问交流。 来源: https://www.cnblogs.com/qq2766022474/p/11784756.html

平面最近点对的分治做法及其证明

匿名 (未验证) 提交于 2019-12-03 00:34:01
2018.6.23 好久没写博客了,做了一道有趣的分治题,写个博客。 题目传送门: P1429 平面最近点对(加强版) 给定平面上n个点,找出其中的一对点的距离,使得在这n个点的所有点对中,该距离为所有点对中最小的 第一行:n;2≤n≤200000 接下来n行:每行两个实数:x y (0≤x,y≤10^9),表示一个点的行坐标和列坐标,中间用一个空格隔开。 仅一行,一个实数,表示最短距离,精确到小数点后面4位。 众所周知,这道题可以分治解决。我们可以对这n个点,以x坐标为第一关键字,y坐标为第二关键字排序。排序后,我们可以把这个点集等分成左右两部分。这样分割以后,所有有可能成为答案的点对就被分为了三部分――1.两个点都在左侧集合,2.两个点都在右侧集合,3.一个点在左侧集合、另一个点在右侧集合。 对于两个点在同一个集合的点对,我们可以递归求解。但对于两个点不在同一个集合的最近点对的求解,却是很棘手的。如果暴力在两侧枚举点然后求距离,时间复杂度就会退化为 O ( n 2 ) O ( n 2 ) ,分治就没有意义了。 其实在两侧暴力枚举点,会得到很多多余的信息。如果在分治处理左右两边的时候,已经求出的最近点对距离为d(d为左半集合答案 与 右半集合答案 的较小值),那么如果我们能确定左侧的一个点到右侧的任何一个点的距离一定大于d的话,那么这个点在枚举点的过程中是可以直接被忽略的。这样

分治[2019.5.25]

匿名 (未验证) 提交于 2019-12-02 23:42:01
  1、为最近对问题的一维版本设计一个直接基于分治技术的算法,并确定它的时间复杂度。假设输入的点是以升序保存在数组A中。(最近点对问题定义:已知上m个点的集合,找出对接近的一对点。)   思路:通过分治和递归将问题自顶向下分为层层的子问题,然后每层中子问题自底向上min向上比较。   输入:保存升序点序列的数组A int Close(int A[a...b]){ if(a==b)return error; else if(b-a==1)return A[b]-A[a]; else{ int c = int((a+b)/2); //多个数时,分治&递归求每个子问题,然后min return min{Close(A[a…c]), Close(A[c...b]), A[c+1]-A[c]}; } }   输出:最近的一对数的距离   时间复杂度:θ(n)   2、设计一个分治算法来计算二叉树的层数.(空树返回0,单顶点树返回1),并确定它的时间复杂度.   思路:水题,对于二叉树T,若为空树,则高度为0;否则,分别求左子树和右子树高度,递归即可。   输入:二叉树T int height(Tree T){ if T=NULL return 0; else return max{height(left_T),height(right_T)}+1; }   输出:二叉树的层数   时间复杂度

CDQ分治入门

匿名 (未验证) 提交于 2019-12-02 23:04:42
cdq分治与其说是算法,不如说是一种解决问题的思想或方式。与常规分治对比,常规分治是通过解决左右两个子区间的问题,合并得到大区间问题的解。但cdq分治通过处理左区间对右区间的影响来得到大区间的解。一般来说,cdq分治可以顶替一层数据结构,而且常数小,空间开销也小。缺点是需要离线。 一般来说,支持离线是cdq分治可行的前提,因为我们要用合理的顺序解决操作和询问的关系,处理左边对右边的影响,逐步得到所有答案。如果碰到一些强制在线的题目,一般cdq分治是做不了的。 以几道经典问题来逐步介绍CDQ分治的思想。 这个基础算法其实就体现了CDQ的思想。在分治的基础上,处理左边对右边的逆序对贡献。这个太基础,不赘述 存在n个二元组(a,b),问存在多少对i,j使得ai<=aj&&bi<=bj。这个问题也可以转化成上述问题。对n个二元组,按第一维升序排列,以忽略a的影响。这时问题就转化成新序列有多少个顺序对了。 两种操作,对位置P加C或询问[L,R]的和。这本该是树状数组解决的问题,但为了学习cdq,我们对其进行转化,也可以转化成上述类似问题。我们这样看待操作,区间求和转化为两个前缀求和的差,以操作时间为第一维,操作的位置为第二维。按第一维时间来排序(一般就是读入的顺序),这样就只考虑操作位置。可以发现只有位置靠左的修改才对位置靠右的前缀求和询问产生影响。左边对右边的贡献就是那些修改的值

【算法概论】分治算法:求主元素

微笑、不失礼 提交于 2019-12-02 20:28:09
时间复杂度:O(n*logn) 将数组A划分成两个数组A1和A2,各含有A中的一半元素。考虑以下的问题:如果知道了A1和A2中各自的主元素,是否会对找出A中的主元素有所帮助? → 分治法 /* 找数组的主元素(主元素的重复次数超过数组大小的一半)。 先将数组划分成两个数组A1和A2,找它们各自的主元素。 */ #include <iostream> #include <limits.h> using namespace std; int Partition(int data[], int head, int tail); int main() { int data[10] = { 5, 5, 3, 4, 4, 4, 4, 5, 5 }; int data[10] = { 5, 5, 5, 3, 4, 4, 5, 5, 4 }; if (Partition(data, 0, 9) != INT_MAX) { cout << Partition(data, 0, 9) << endl; } else { cout << "该数组没有主元素" << endl; } return 0; } int Partition(int data[], int head, int tail) { //划分到子数组只有一个元素,返回该元素 if (head == tail) { return data

2019E1_E 分治

偶尔善良 提交于 2019-12-02 10:30:16
E 分治 题目 知识点 分治,分而治之。就是把一个复杂的问题分成两个或更多的相同或相似的子问题,直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。 通常对一维序列,都是分解为两个子问题,l-mid,mid-r。 常见的分治算法,归并排序,二分等等。 练习题 逆序对的个数。 逆序对的定义:在一个序列a 中,如果i<j 且 ai>aj 那么aiaj 就是一个逆序对。 输入 第一行一个数n,表示序列的长度。(1≤n≤105 ) 接下来一行,n个整数,保证在int范围内 输出 一行一个数,表示逆序对的个数 输入样例 5 1 2 3 4 5 输出样例 0 思路 分治 代码 unsigned long long merge ( vector < int > & a , int l , int mid , int r ) { unsigned long long count = 0 ; int p1 = l ; int p2 = mid + 1 ; unsigned long long i = 0 ; vector < int > help ( r - l + 1 ) ; //将包含r-l+1个(从l到r的数的个数 while ( p1 <= mid && p2 <= r ) { count + = a [ p1 ] > a [ p2 ] ? ( mid - p1 + 1 ) :

P3806 - 点分治

折月煮酒 提交于 2019-12-02 06:43:05
题目链接: https://www.luogu.org/problem/P3806 思路: 点分治是一种基于树的重心,统计树上路径的优秀算法。 将树上的路径分为经过根节点和不经过根节点两种 ,对于前者, 我们用 表示结点 到根节点 的路径长度, 则 到 的路径长为 , 对于后者,如果把根节点删掉,则可以 生成若干颗以原根节点的儿子为根节点的子树 ,对于这些子树又可以分为经过根节点和不经过根节点两种。 所以点分治步骤大概是: 处理根节点的所有路径 删掉根节点 对生成的每颗子树的根节点重复1,2步骤 如果树退化成一条链 , 那么递归层数就是 ,总时间复杂度为 ,显然不行。 所以我们要找树的重心,点分治过程中 每次选取子树的重心为子树的根节点进行处理 , 这样 总的递归深度不会超过 层 , 整个点分治的时间复杂度也就保证了 。 最终点分治的步骤是这样的: 找到当前树的重心 处理根节点的所有路径 删掉根节点 对于生成所有的子树,重复以上步骤 #include <bits/stdc++.h> using namespace std; const int maxn = 1e4+5; const int maxk = 1e7+5; struct E { int to, w, next; }Edge[maxn<<1]; int tot, head[maxn]; inline void

C++分治策略实现线性时间选择

China☆狼群 提交于 2019-12-01 16:37:28
问题描述: 给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k小的元素,即如果将这n个元素依其线性序排列时,排在第k个的元素即为要找到元素。 细节须知:(与之前的随笔相比) (1)设置了对于程序运行次数的手动输入设定 (2)取消了文件的读入,直接生成随机数进行排序查找 (3)扩大了随机数的范围、数组的可申请大小 (4)时间统计精确到了微秒级 (5)运行结束后一次性写入提升了程序稳定性,写入的数据可用于数据分析图表 算法原理: 将n个输入元素划分成⌈n/5⌉个组,每组5个元素,只可能有一个组不是5个元素。用任意一种排序算法,将每组中的元素排好序,并取出每组的中位数,共⌈n/5⌉个。递归调用算法Select来找出⌈n/5⌉个元素的中位数。如果⌈n/5⌉是偶数,就找它的两个中位数中较大的一个。以这个元素作为划分基准。以此递归排序找到所需的第k项。 1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<fstream> 6 #include<algorithm> 7 #include<windows.h> 8 #include<ctime> 9 using namespace std; 10 LARGE_INTEGER nFreq;/

分治

爷,独闯天下 提交于 2019-12-01 16:34:45
分治算法 判断某个元素是否在列表中 ''' 判断某个元素是否在列表中 ''' def is_in_list(init_list,el): return [False,True][init_list[0]==el] #分治法 def solve(init_list,el): n=len(init_list) if n==1: return is_in_list(init_list,el) #分解 left_list,right_list=init_list[:n//2],init_list[n//2:] #合并 res=solve(left_list,el) or solve(right_list,el) return res if __name__ == '__main__': #测试数据 test_list=[12,2,23,45,67,3,2,4,45,63,24,23] #查找 print(solve(test_list,45)) print(solve(test_list,5)) View Code 求顺序表中最大值 ''' 求顺序表中最大值 ''' #基本子算法 def get_max(max_list): return max(max_list) #分治法 def solve2(init_list): n=len(init_list) if n<=2: return

点分治&&动态点分治学习笔记

依然范特西╮ 提交于 2019-12-01 13:22:03
P4149 [IOI2011]Race 题目描述 给一棵树,每条边有权。求一条简单路径,权值和等于 K K,且边的数量最小。 输入格式 第一行包含两个整数 n, K n , K。 接下来 n - 1 n − 1 行,每行包含三个整数,表示一条无向边的两端和权值。 注意点的编号从 0 0 开始。 输出格式 输出一个整数,表示最小边数量。 如果不存在这样的路径,输出 -1 − 1。 输入输出样例 输入 #1 复制 4 3 0 1 1 1 2 2 1 3 4 输出 #1 复制 2 说明/提示 保证 n \leqslant 2 \times 10^5, n ⩽ 2 × 1 0 5 , K \leqslant 10^6 K ⩽ 1 0 6。 这道题目我是在cf161D的基础上进行操作的,在维护距离的时候,顺带维护一下边数就可以。 具体细节代码写了注释,心塞,初始化写挫了,调了两天。。。 学习博客推荐: 点分治&动态点分治小结 点分治详细解析 点分治&&动态点分治学习笔记 【算法学习】点分治的两种写法与常见套路总结 还有一个,没看,关于求重心的 一种基于错误的寻找重心方法的点分治的复杂度分析 代码: 1 //点分治 2 #include<bits/stdc++.h> 3 using namespace std; 4 typedef long long ll; 5 #pragma GCC