5算法设计技术1-蛮力法和分治法_823204234
第15章 基本的算法设计技术
例15.1 设计程序计算an的值。要求用蛮力法。
解:由于an = a * a * …… * a,因此,最直接最简单的想法就是 设变量result保存计算结果并初始化为1,然后将result和a相乘n次。 程序如下:
程序设计基础
15.1
蛮力法
2 #include <stdio.h> 3 4 int main( ) 5 { 6 int a, n; 7 long int result = 1; 8 printf("请输入a的值和n的值:"); 9 scanf("%d%d", &a, &n); 10 for (int i = 1; i <= n; i++) 11 result = result * a; 12 printf("%d的%d次方等于%d\n", a, n, result); 13 return 0; 14 }
程序设计基础
第 12章 预处理
本章的基本内容是:
蛮力法 穷举法 递推法
分治法
动态规划法ຫໍສະໝຸດ 贪心法程序设计基础15.1
蛮力法
算法设计技术(也称算法设计策略)是设计算法的一般性方法,本 章讨论基本的算法设计技术,更深入的内容将在“算法设计与分析 ”课程中介绍。
15.1.1 设计思想
蛮力法采用一定的策略依次处理待求解问题的所有数据,从而找出 问题的解。蛮力法是一种简单直接地解决问题的方法,常常直接基 于问题的描述,所以,蛮力法也是最容易应用的方法
程序设计基础
15.2
15.2.1 设计思想
穷举法
穷举法本质上属于蛮力法,是将所有可能的解都列举出来,依次试探这些解是否满足 特定的条件或要求。前面的程序设计实例“鸡兔同笼问题”、“ 百元买百鸡问题”等都 属于穷举法。穷举法通常需要解决以下两个关键问题: (1)分析问题的解可能存在的范围,找出穷举范围; (2)分析问题的解所满足的条件,找出约束条件并用逻辑表达式表示
分治算法-最大子数组问题
分治算法-最⼤⼦数组问题1.蛮⼒法求解总体思路: 蛮⼒法是最简单的实现⽅法,只要列出数组所有可能的组合,然后找出其中和最⼤的组合即可; 蛮⼒法分三层循环实现: 1)第⼀层循环⽤于固定⼦数组的起始位置; 2)第⼆层循环⽤于确定⼦数组的结束位置; 3)第三层循环⽤于⼦数组和的计算,从⼦数组的头开始遍历到其尾,累加起来就是该⼦数组的和。
实现:///<summary>///暴⼒求解///</summary>///<param name="priceArray"></param>///<param name="priceFlutuationsArray"></param>public static void Violentsolution(int[] priceArray,int[] priceFlutuationsArray){int total = priceFlutuationsArray[0];//默认数组得第⼀个元素是最⼤⼦数组int StartIndex = 0;int EndIndex = 0;for (int i = 0; i < priceFlutuationsArray.Length; i++){//取得以i为⼦数组起点得所有⼦数组for (int j = i; j < priceFlutuationsArray.Length; j++){//由i j就确定了⼀个⼦数组int totalTemp = 0;//临时最⼤⼦数组得和for (int k = i; k < j + 1; k++){totalTemp += priceFlutuationsArray[k];}if (totalTemp > total){total = totalTemp;StartIndex = i;EndIndex = j;}}}Console.WriteLine("start:" + StartIndex);Console.WriteLine("End:" + EndIndex);Console.WriteLine("购买⽇期是第" + StartIndex + "天出售⽇期是第" + (EndIndex + 1) + "天");Console.WriteLine("total:" + total);}2.分治法求解总体思路: 分治法的精髓: 1)分--将问题分解为规模更⼩的⼦问题; 2)治--将这些规模更⼩的⼦问题逐个击破; 3)合--将已解决的⼦问题合并,最终得出“母”问题的解; 所以原数组的最⼤⼦数组求法: 1)分--将原数组拆分成两部分,每个部分再拆分成新的两部分......直到数组被分得只剩下⼀个元素; 2)治--每个⼩型的数组找最⼤⼦数组,只有⼀个元素的数组,解就是该元素; 3)合--将两个⼩型数组合并为⼀个数组,其中解有三种可能:左边的返回值⼤,右边的返回值⼤,中间存在⼀个更⼤的⼦数组和; 返回值应选最⼤的;实现:using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace最⼤⼦数组问题{class Program{//最⼤⼦数组的结构体struct SubArray{public int startIndex;public int endIndex;public int total;}static void Main(string[] args){int[] priceArray = { 100, 113, 110, 85, 105, 102, 86, 63, 81, 101, 94, 106, 101, 79, 94, 90, 97 };int[] pf = new int[priceArray.Length - 1];//价格波动的数组for (int i = 1; i < priceArray.Length; i++){pf[i - 1] = priceArray[i] - priceArray[i - 1];}SubArray subArray = GetMaxSubArray(0, pf.Length - 1, pf);Console.WriteLine(subArray.startIndex);Console.WriteLine(subArray.endIndex);Console.WriteLine("我们在第" + subArray.startIndex + "天买⼊,在第" + (subArray.endIndex + 1) + "天卖出");Console.ReadKey();}///<summary>///这个⽅法⽤来取得array这个数组从low到high得最⼤⼦数组///</summary>///<param name="low"></param>///<param name="high"></param>///<param name="array"></param>static SubArray GetMaxSubArray(int low,int high,int[] array){if (low == high){SubArray subarray;subarray.startIndex = low;subarray.endIndex = high;subarray.total = array[low];return subarray;}int mid = (low + high)/2; //低区间[low,mid] ⾼区间[mid+1,high]SubArray subArray1= GetMaxSubArray(low, mid, array);SubArray subArray2=GetMaxSubArray(mid+1, high, array);SubArray subArray3 = GetMaxSub(low, mid, high, array);if (subArray1.total >= subArray2.total && subArray1.total >= subArray3.total){return subArray1;}else if (subArray2.total >= subArray1.total && subArray2.total >= subArray3.total){return subArray2;}else{return subArray3;}}static SubArray GetMaxSub(int low,int mid,int high,int[] array){//从【low,mid】找到最⼤⼦数组[i,mid]int total1 = array[mid];int startIndex = mid;int totalTemp = 0;for (int i = mid; i >= low; i--){totalTemp += array[i];if (totalTemp > total1){total1 = totalTemp;startIndex = i;}}//从【mid+1,high】找到最⼤⼦数组[mid+1,j]int total2 = array[mid + 1];int endIndex = mid + 1;totalTemp = 0;for (int j = mid + 1; j <= high; j++) {totalTemp += array[j];if (totalTemp > total2){total2 = totalTemp;endIndex = j;}}SubArray subArray3;subArray3.startIndex = startIndex; subArray3.endIndex = endIndex; subArray3.total = total1 + total2;return subArray3;}}}。
五大算法设计思想(转载)
五⼤算法设计思想(转载)⼀分治法1.1 概念: 将⼀个难以直接解决的⼤问题,分割成⼀些规模较⼩的相同问题,以便各个击破,分⽽治之。
1.2 思想策略: 对于⼀个规模为n的问题,若该问题可以容易地解决(⽐如说规模n较⼩)则直接解决,否则将其分解为k个规模较⼩的⼦问题,这些⼦问题互相独⽴且与原问题形式相同,递归地解这些⼦问题,然后将各⼦问题的解合并得到原问题的解。
1.3 特征:1) 该问题的规模缩⼩到⼀定的程度就可以容易地解决2) 该问题可以分解为若⼲个规模较⼩的相同问题,即该问题具有最优⼦结构性质。
3) 利⽤该问题分解出的⼦问题的解可以合并为该问题的解;4) 该问题所分解出的各个⼦问题是相互独⽴的,即⼦问题之间不包含公共的⼦⼦问题。
1.4 对特征的解析:第⼀条特征是绝⼤多数问题都可以满⾜的,因为问题的计算复杂性⼀般是随着问题规模的增加⽽增加;第⼆条特征是应⽤分治法的前提它也是⼤多数问题可以满⾜的,此特征反映了递归思想的应⽤;第三条特征是关键,能否利⽤分治法完全取决于问题是否具有第三条特征,如果具备了第⼀条和第⼆条特征,⽽不具备第三条特征,则可以考虑⽤贪⼼法或动态规划法。
第四条特征涉及到分治法的效率,如果各⼦问题是不独⽴的则分治法要做许多不必要的⼯作,重复地解公共的⼦问题,此时虽然可⽤分治法,但⼀般⽤动态规划法较好。
1.5 基本步骤:1 分解:将原问题分解为若⼲个规模较⼩,相互独⽴,与原问题形式相同的⼦问题;2 解决:若⼦问题规模较⼩⽽容易被解决则直接解,否则递归地解各个⼦问题3 合并:将各个⼦问题的解合并为原问题的解。
1.6 适⽤分治法求解的经典问题:1)⼆分搜索2)⼤整数乘法3)Strassen矩阵乘法4)棋盘覆盖5)合并排序6)快速排序7)线性时间选择8)最接近点对问题9)循环赛⽇程表10)汉诺塔⼆动态规划2.1 概念 每次决策依赖于当前状态,⼜随即引起状态的转移。
⼀个决策序列就是在变化的状态中产⽣出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划。
五大经典算法介绍
1分治法1.1基本概念在计算机科学中,分治法是一种很重要的算法。
字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。
这个技巧是很多高效算法的基础,如排序算法(快速排序,归并排序),傅立叶变换(快速傅立叶变换)……任何一个可以用计算机求解的问题所需的计算时间都与其规模有关。
问题的规模越小,越容易直接求解,解题所需的计算时间也越少。
例如,对于n个元素的排序问题,当n=1时,不需任何计算。
n=2时,只要作一次比较即可排好序。
n=3时只要作3次比较即可,…。
而当n较大时,问题就不那么容易处理了。
要想直接解决一个规模较大的问题,有时是相当困难的。
1.2基本思想及策略分治法的设计思想是:将一个难以直接解决的大问题,分割成一些规模较小的相同问题,以便各个击破,分而治之。
分治策略是:对于一个规模为n的问题,若该问题可以容易地解决(比如说规模n较小)则直接解决,否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解这些子问题,然后将各子问题的解合并得到原问题的解。
这种算法设计策略叫做分治法。
如果原问题可分割成k个子问题,1<k≤n,且这些子问题都可解并可利用这些子问题的解求出原问题的解,那么这种分治法就是可行的。
由分治法产生的子问题往往是原问题的较小模式,这就为使用递归技术提供了方便。
在这种情况下,反复应用分治手段,可以使子问题与原问题类型一致而其规模却不断缩小,最终使子问题缩小到很容易直接求出其解。
这自然导致递归过程的产生。
分治与递归像一对孪生兄弟,经常同时应用在算法设计之中,并由此产生许多高效算法。
1.3分治法适用的情况分治法所能解决的问题一般具有以下几个特征:1) 该问题的规模缩小到一定的程度就可以容易地解决2) 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质。
蛮力算法
17
main1( ) { int *a,i,j,n; input(n); a=calloc(n+1,sizeof(int)); //申请存储空间 for (i=1; i<=n;i++) a[i]=1; for (i=1; i<=n;i++) for (j=i; j<=n;j=j+i) a[i]=1-a[i]; for (i=1; i<=n;i++) if (a[i]=0) print(i,”is free.”); } 算法分析1:以一次开关锁计算,算法的时间复杂度为 n(1+1/2+1/3+……+1/n)=O(nlogn)。
3
【例3.1】百钱百鸡问题。中国古代数学家张丘建在《算经》 中提出了著名的“百钱百鸡问题”:鸡翁一,值钱五;鸡母一, 值钱三;鸡雏三,值钱一;百钱买百鸡,翁、母、雏各几何? 算法设计1: 通过对问题的理解,可能会想到列出两个三元一次方程, 去解这个不定解方程,就能找出问题的解。这确实是一种办法, 但这里我们要用“懒惰”的枚举策略进行算法设计: 设x,y,z分别为公鸡、母鸡、小鸡的数量。 尝试范围:由题意给定共100钱要买百鸡,若全买公鸡最多 买100/5=20只,显然x的取值范围1~20之间;同理,y的取值范 围在1~33之间,z的取值范围在1~100之间。 约束条件: x+y+z=100 且 5*x+3*y+z/3=100
实验项目1:蛮力法与分治法应用
实验项目1:蛮力法与分治法应用1、目的与要求:实验目的:了解蛮力法和分治法的基本思想,学会运用蛮力法和分治法解决实际系统设计应用中碰到的问题。
实验要求:用蛮力法实现选择、冒泡排序,或旅行商问题、背包问题等问题(任选其中之一)。
用分治法实现合并排序或快速排序。
要求写出算法的伪代码描述,并编写程序实现之,相关算法放在函数内实现,主程序给出测试用例,要设计足够多的相关测试用例,验证程序的正确性。
注意观察程序执行结果和运行的时间。
实验报告要求给出问题定义及算法的伪代码描述,程序设计的代码,算法的测试用例及结果,并分析算法的时间效率,回答指导书中的思考题。
2、实验内容:(2)用分治法实现快速排序、合并排序算法。
本实验主要是用分治法实现合并排序,快速排序程序等。
合并排序算法描述:MergeSort ( A[0...p-1] )// input 待排序数组A[0..n-1]// output 非降序排列的数组A[0..n-1]if ( n>1 ) {//至少有2个元素Copy A[0.. n/2-1 ] to B[0.. n/2-1 ];Copy A[n/2..n-1 ] to C[0.. n/2-1 ];MergeSort ( B[0.. n/2-1 ] );MergeSort (C[0.. n/2-1 ]t);Merge (B, C, A); //复制回数组a快速排序算法描述:QuickSort ( A[1.. r ] ){if (l<r) s=Partition( A[l,r] ); // s 是分裂位置QuickSort ( A[l..s-1] ); //对左半段排序QuickSort ( A[s+1,r); //对右半段排序}Partition ( A[l..r] ){p=A[[l] ;i = l; j = r + 1;repeatedrepeated i=i+1; until A[i]> p // 将>= x的元素交换到左边区域repeated i=i+1; until A[i]> p // <= x的元素交换到右边区域Swap( A[i], A[j] )Until i>jSwap( A[i] = a[j] );Swap( A[l], A[j] )return j;要求先给出算法的伪代码,然后用C++或其他程序设计语言编写程序实现之,并设计相关的测试用例,验证程序的正确性。
《算法设计与分析基础》课件-3.蛮力法
if A[j] < A[min] min j
swap A[i] and A[min]
7
2017/12/31
例题:对序列 {89,45,68,90,29,34,17}用选择排序 算法进行排序
• 第1遍: {89,45,68,90,29,34,17} //求最小元素 {17,45,68,90,29,34,89} //交换
• 第5遍: {17,29,34,45,90,68,89} {17,29,34,45,68,90,89}
• 第6遍: {17,29,34,45,68,90,89} {17,29,34,45,68,89,90} //排序结束
8
CHD
(本动画中,参与排序的是R[1]到R[n],R[0]作为交换中转的空 间;变量j对应前面算法中的变量min)
2017/12/31
ALGORITHM BubbleSort(A[0,…,n – 1]) // 冒泡排序算法在数组上的应用 // 输入:数组A,数组中的元素属于某偏序集 // 输出:按升序排列的数组A for i 0 to n – 2 do
for j 0 to n – 2 – i do if A[j+1] < A[j] swap(A[j], A[j+1])
CHD
(4)对解决一些小规模的问题实例仍然有效
(5)可作为衡量其他算法的参照。
2
2017/12/31
Brute Force Examples:
1. Computing an (a > 0, n a nonnegative integer)
2. Computing n!
3. Multiplying two matrices
最新《算法设计与分析》蛮力法
100,101,102,103,110,111,112, 120,121,122,130,200,201,202, 211,212,220,221,300,301,310。 不难验证只有100,101两个数符合要求。
算法设计1: 1)一维数组a[n]记录n个锁的状态
1:被锁上 0:被打开
2)对i号锁的一次开关锁可以转化为算术运算: a[i]=1-a[i]。
3)第一次转动的是1,2,3,……,n号牢房; 第二次转动的是2,4,6,……号牢房; 第i次转动的是i,2i,3i,4i,……号牢 房,是起点为i,公差为i的等差数列。
《算法设计与分析》蛮力法
蛮力法 Brute Force
• 蛮力法不是一个最好的算法(巧妙和高效的算法 很少出自蛮力),但当我们想不出更好的办法时, 它也是一种有效的解决问题的方法。
• 它可能是惟一一种几乎什么问题都能解决的一般 性方法,常用于一些非常基本、但又十分重要的 算法,比如计算n个数字的和,求一个列表的最 大元素等等。
约束条件: x+y+z=100 且 5*x+3*y+z/3=100
算法1如下: main( ) 枚举尝试20*34*100=68000次 { int x,y,z; for(x=1;x<=20;x=x+1) for(y=1;y<=34;y=y+1)
for(z=1;z<=100;z=z+1) if(100==x+y+z&&100==5*x+3*y+z/3) {print("the cock number is",x); print("the hen number is", y);
5算法设计技术1-蛮力法和分治法_823204234
c1 = af * bl + al * bf = (af + al) * (bf + bl) - (c2 + c0)
数据结构 (30230594)
18
吴及 电子工程系
大整数乘法
乘法的复杂度 T(n) = 3T(n/2)
的正确性和效率
数据结构 (30230594)
10
吴及 电子工程系
内容提要
算法设计技术
蛮力法 分治法 贪心算法 动态规划 搜索算法
数据结构
11
(30230594)
吴及 电子工程系
分治法
基本思想
把问题的一个实例分解成为属于同一问题的若干个较小规模的实例 重复这个过程直到规模较小的实例很容易求解, 求解这些规模较小的实例, 合并较小问题的解,以得到原始问题的解。
握某个特定算法更重要
数据结构 (30230594)
2
吴及 电子工程系
内容提要
算法设计技术 算法优化技术 计算复杂性理论简介
数据结构 (30230594)
3
吴及 电子工程系
内容提要
算法设计技术
蛮力法 分治法 贪心算法 动态规划 搜索算法
数据结构
4
(30230594)
吴及 电子工程系
全部公因子cf1, cf2, cf13…… 这个公因子序列中最大的cfk,即为m和n的最大公因子 或者从m到2,逐个判断每个整数是否可以同时整除m和n,找到的第一个
能够同时整除m和n的整数就是最大公因子
针对蛮力法的优化 其它方法
数据结构 (30230594)
算法设计(第3章蛮力法)
d = dx*dx + dy*dy;
if (d<d_best) then
d_best d;
(a,b) (i,j);
return (a,b);
时间复杂度O(n2):存在改进可能?
end
3.5.2 (0-1)背包问题
输入:n件物品的集合S (其中第i件物品的重量 和价值分别为S[i].w和S[i].v),以及背包的最大 承重量W
[最小顶点覆盖问题的蛮力算法]
Algorithm Brute_VertexCover(V: set<int>; E: set<intint>)
begin
let C = V;
foreach V’ Powerset(V) do
let cover = true;
foreach ((u,v) E) do
3.1 字符串匹配
蛮力法:从左到右扫描T,检查T中是否含有子串P
m i c r o s o f t wi n dows sof t
匹配成功,返回位置索引5
3.1 字符串匹配
[字符串匹配算法] Algorithm Brute_Match(T, P: string) begin let i = 0, n = |T|, m = |P|; while (i ≤ n−m) do
时间复杂度O(n2)
3.5 若干最优化问题最优化问 Nhomakorabea:在问题的可行域F中找到一个解x, 使得某目标函数值f(x)最小或最大。
约束条件:解x应满足某项约束c(x)=true 连续优化问题:解的数量可能有无穷多 组合优化问题:解的数量有限时,总是可以用
蛮力法求解,但算法效率可能很低。
3.5 若干最优化问题
算法设计与分析蛮力法
算法分析与设计
14
算法1如下:
input(n);//输入n
a=new int(n+1);
for (i=1; i<=n;i++)
a[i]=1;
for (i=1; i<=n;i++)
if(100==x+y+z&&100==5*x+3*y+z/3) {print("the cock number is",x); print("the hen number is", y);
print("the chick number is ",z);} }
算法分析与设计
8
算法分析与设计
9
Z能被3整除时,才会判断“5*x+3*y+z/3=100
print("the chick number is ",z);} } }
算法分析与设计
10
例2
• 求所有的三位数,它除以11所得的余数等 于它的三个数字的平方和。
解题思路:三位数只有900个,可用枚举 法解决,枚举时可先估计有关量的范围, 以缩小讨论范围,减少计算量。
算法分析与设计
11
• 解:设这个三位数的百位、十位、个位的数字分别为 x,y,z。由于任何数除以11所得余数都不大于10, 所以
蛮力法 Brute Force
• 蛮力法(枚举法、穷举法,暴力法)要求设计 者找出所有可能的方法,然后选择其中的一种 方法,若该方法不可行则试探下一种可能的方 法。
算法设计与分析4第三部分第三章
第三部分第三章 蛮力法
分析该算法的效率: 分析该算法的效率: S1:确定输入规模的参数为n S1:确定输入规模的参数为n S2:基本操作是内层循环体中的比较运算 S2: S3:基本操作次数的计算:外层循环执行次数为N S3:基本操作次数的计算:外层循环执行次数为N-1 内层循环执行次数为N 我们可以用求和公式给出: 次,内层循环执行次数为N-i-1次,我们可以用求和公式给出: =n(nC(n)= n − 2 n −1 =n(n-1)/2∈θ(n2)
第三部分第三章 蛮力法
排序问题是我们经常见到的,当前, 排序问题是我们经常见到的,当前,人们已经开 发出了几十种排序方法。 发出了几十种排序方法。 1、选择排序 排序思想:首先从要排序的数中选择最小的数与 排序思想: 第一个数交换位置, 第一个数交换位置,然后再从乘下的数中再 找出最小的数与第二个数交换位置, 找出最小的数与第二个数交换位置,直到剩 下两个数, 下两个数,我们选择较小的数放到倒数第二 个位置,经过n 轮这样的操作后, 个位置,经过n-1轮这样的操作后,数就按 从小到大的顺序排好了。 从小到大的顺序排好了。
第三部分第三章 蛮力法
第三,如果要解决的问题实例不多, 第三 , 如果要解决的问题实例不多 , 而且蛮力法可 以用一种能够接受的速度对实例求解,那么, 以用一种能够接受的速度对实例求解 , 那么 , 设 计一个更高效算法所花费的代价很可能是不值得 的。 第四,即使效率通常很低, 第四 , 即使效率通常很低 , 仍然可以用蛮力算法解 决一些小规模的问题实例。 决一些小规模的问题实例。 最后,一个蛮力算法可以为研究或教学目的服务, 最后 , 一个蛮力算法可以为研究或教学目的服务 , 可以用它来恒量同样问题的更高效的算法。 可以用它来恒量同样问题的更高效的算法。
中科大软院算法导论最近点对算法_C++
实验四求最近点对算法1.算法设计思路:设共有n个点,找其中距离最近的两点及其距离。
(1)蛮力法:蛮力法的思路是把所有点之间距离比较找出中间最小的。
先假设最短距离是第一个元素和第二个元素的距离,然后求第一个元素与其后的(n-1)个元素各自的距离,若比之前记录的最短距离小则记录当前值···求第i个元素与其后的(n-i)个元素各自的距离,记录之前所得到的所有距离中的最小值,直到计算到第(n-1)个元素与第n个元素的距离,此时记录的距离即为这n个元素中的最短距离。
(2)分治法:分治法是把一个大的问题划分成相似的小问题,采用递归的思想。
找中线把n个元素分成左右两部分元素分别求得两边的最短距离,然后取两者中的最小者记为l,在中线两边分别取l的距离,记录该距离范围内点的个数,中线左边有L个元素,右边有R个元素,求左边元素到右边元素的距离看其是否小于之前记录的最短距离,小则记录下来,此时的右边元素只取y值和左边元素y值距离小于l的(减少循环次数)。
循环结束即可找到最小的距离。
2.程序代码:#include<iostream>#include<cstdlib>#include<ctime>#include<cmath>using std::cout;using std::endl;#define N 5int x[N],y[N],record[N]; //产生原始点数据,x坐标放在x[]中,y坐标放在y[]中。
double Min;//////////////////////////产生随机数组/////////////////////////////void randnum(){int i;srand(time(0));for (i=0;i<N;i++){x[i]=rand()%N;cout<<x[i]<<' ';}cout<<endl;for (i=0;i<N;i++){y[i]=rand()%N;cout<<y[i]<<' ';}cout<<endl;}//////////////////////////////交换数组元素/////////////////////////// void swap(int & a, int & b){int temp=a;a=b;b=temp;}///////////////////////////////求平方///////////////////////////////////int square(int x){return x*x;}/////////////////////////////////////求两点之间距离////////////////////double lengthf(int x1,int y1,int x2,int y2){return sqrt(square(x1-x2)+square(y1-y2));}//////////////////////////////////求两者中最小者////////////////////// double min(double a,double b){if (a>=b)return b;elsereturn a;}////////////////////////////对平面数组排序//////////////////////////// void sort(int A[]){int i,j;for (i=0;i<N;i++)record[i]=i;for (j=1;j<N;j++){i=j;while (i>=0&&A[i]<A[i-1]){swap(A[i],A[i-1]);swap(record[i-1],record[i]); //得到x排序后对应的原y的坐标i--;}}cout<<"排序后的元素数组:"<<endl;for (i=0;i<N;i++)cout<<A[i]<<' ';cout<<endl;for (i=0;i<N;i++)cout<<record[i]<<' ';cout<<endl;}///////////////////////////穷举法找最小点对///////////////////////////////double exhaustion(){int i,j,k1,k2;double num;double length;num=10000;k1=k2=-1;for (j=0;j<N-1;j++){for (i=j+1;i<N;i++){length=lengthf(x[i],y[i],x[j],y[j]);if (length<num){num=length;k1=i;k2=j;}}}cout<<"平面数组最短距离是:"<<endl;cout<<"min="<<num<<endl;cout<<"对应数组下标及点坐标为:"<<endl;cout<<"i="<<k1<<','<<k2<<endl;cout<<"(x1,y1)="<<'('<<x[k1]<<','<<y[k1]<<')'<<endl<<"(x2,y2)="<<'('<<x[k2]<<','<<y[k2]<<')' <<endl;return num;}////////////////////////////////////分治法////////////////////////////////*************************************************************************/double merge(int left,int right){double mlength;if (right==left)mlength=10e-6;if (right==left+1)mlength=lengthf(x[right],y[record[right]],x[left],y[record[left]]); //两个点时求最小值if (right-left==2)mlength=min(min(lengthf(x[right-1],y[record[right-1]],x[left],y[record[left]]),lengthf(x[right],y[re cord[right]],x[left+1],y[record[left+1]])),lengthf(x[right],y[record[right]],x[left],y[record[left]]));//三个点时求最大值return mlength;}double divide(int left,int right){if (right-left<=2){Min=merge(left,right);}else{double l1,l2,mi; //l1记录划分区域后左半面最小距离,l2记录右半面最小距离,min为两者中较小者,m为全部中的最小者int rem1,rem2,l; //记录获得最短距离对应的两个点//int il,jl,ir,jr;int i,j;int R,L;R=L=0; //记录划分小区域后的左半块和右半块个有多少元素l1=l2=Min=100;l=(right-left+1)/2-1; //中线位置///////////////////////////////////////////////////l1=divide(left,l);l2=divide(l+1,right);if (l1<l2){Min=l1;//cout<<"两半面最短距离是:"<<min;else{Min=l2;//cout<<"两半面最短距离是:"<<min;}///////////////////得到右半块元素数R//cout<<"min="<<min<<endl;for (i=l+1;i<N;i++){if (x[i]-x[l]<=Min)R++;else break;}//cout<<"R="<<R<<endl;/////////////////////得到左半块元素数Lfor (i=l;i>=0;i--){if (x[l]-x[i]<=Min)L++;else break;}//cout<<"L="<<L<<endl;if (L!=0&&R!=0){for (i=l-L+1;i<=l;i++)for (j=l+1;j<=l+R;j++){if (y[record[j]]-y[record[i]]<Min||-Min<y[record[j]]-y[record[i]]){mi=lengthf(x[i],y[record[i]],x[j],y[record[j]]);if (mi<Min){Min=mi;rem1=i;rem2=j;}}}// cout<<"min="<<min<<endl;//cout<<"rem1="<<rem1<<endl<<"rem2="<<rem2<<endl;}return Min;}/***********************************************************************///////////////////////////////////主函数///////////////////////////////////int main(){//double a;randnum();cout<<"***************************遍历法*************************"<<endl;exhaustion();cout<<"***************************分治法*************************"<<endl;sort(x);divide(0,N-1);cout<<"元素组中最短距离为:"<<endl;cout<<"min="<<Min<<endl;return 0;}3.实验数据及实验结果:实验数据:随机产生的五个点坐标分别为:(1,3),(4,2),(3,0),(2,0),(0,3)实验结果:用蛮力法得到平面数组最短距离为:min=1用分治法得到平面数组最短距离为:min=14.实验总结:从本次试验中得到的领悟是:分治法事把问题分解成两个相似小问题,子问题和原来的大问题解决方法一样所以可以用递归,分治法重要是找到递归出口,什么时候递归结束,一般都有元素个数的限制。
算法设计与分析-第四章1-常用算法策略迭代蛮力分治PPT课件
.
4
数学建模:y1=y2=1,yn=yn-1+yn-2,n=3,4,5,……。
算法1:
main( ) { int i,a=1,b=1;
print(a,b); for(i=1;i<=10;i++)
{ c=a+b; print (c); a=b; b=c;
} }
.
5
算法2:
表4-1 递推迭代表达式
12 3
.
21
【例2】牛顿迭代法 牛顿迭代法又称为切线法,它比一般的迭代法有更高的收敛速度,如图 4-5所示。首先, 选择一个接近函数f(x)零点的x0, 计算相应的f(x0)和 切线斜率f‘(x0)(这里f ’表示函数f的导数)。然后我们计算穿过点 (x0,f (x0))且斜率为f ‘(x0)的直线方程为:
{a[1]=a[i]=1; for (j=i-1,j>1,j=j-1) a[j]=a[j]+a[j-1];
for (j=1;j<=i;j=j+1) print(a[j]); print(“换行符”);
} }
.
13
【例3】穿越沙漠问题 用一辆吉普车穿越1000公里的沙漠。吉普车的总装油量为500加仑, 耗油率为1加仑/公里。由于沙漠中没有油库,必须先用这辆车在 沙漠中建立临时油库。该吉普车以最少的耗油量穿越沙漠,应在 什么地方建油库,以及各处的贮油量。
问题分析:题目中要求用一个一维数组即完成。 1 4 6 4 1
数组空间一定是由下标从小到大利用的,这 ……………
样其实杨辉三角形是按下图4-2形式存储的。 图4-1 杨辉三角形
若求n层,则数组最多存储n个数据。
算法设计:
A[1] = A[i]=1 A[j] = A[j] + A[j-1] i行 i-1行 i-1行
蛮力法和分治法的性能比较
蛮力法与分治法求解最近对问题1、蛮力法蛮力法是一种简单直接地解决问题的方法,常常直接基于问题的描述和所涉及的概念定义,来求解问题。
虽然巧妙和高效的算法很少来自于蛮力法,但它仍是一种重要的算法设计策略:(1)适用泛围广,是能解决几乎所有问题的一般性方法;(2)常用于一些非常基本、但又十分重要的算法(排序、查找、矩阵乘法和字符串匹配等);(3)解决一些规模小或价值低的问题;(4)可以做为同样问题的更高效算法的一个标准;(5)可以通过对蛮力法的改进来得到更好的算法。
2、分治法分治法,就是分而治之即把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题直到问题解决。
分治法在求解问题时,效率比较高,也是一种重要的算法策略:(1)该问题的规模缩小到一定的程度就可以容易地解决;(2)该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质;(3)利用该问题分解出的子问题的解可以合并为该问题的解;(4)该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。
算法的基本思想及复杂度分析1.蛮力法(1)基本思想蛮力法求解最近对问题的过程是:分别计算每一对点之间的距离,然后通过排序找出距离最小的一对,为了避免对同一对点计算两次距离,只考虑i<j的那些点对(P i,P j)。
(2)复杂度分析算法的基本操作是计算两个点的欧几里得距离。
在求欧几里得距离时,我们要避免求平方根操作,因为求平方根时要浪费时间,而在求解此问题时,求解平方根并没什么更大的意义。
如果被开方的数越小,则它的平方根也越小。
因此,算法的基本操作就是求平方即可,其执行次数为:T(n)=∑-=11n i ∑+=n i j 12 =2∑-=-11)(n i i n =n (n-1)=O (n2) 2.分治法(1)基本思想用分治法解决最近对问题,就是将集合S 分成两个子集S1和S2,每个子集中有n/2个点。
实验报告 蛮力分治动态最大字段
《算法设计与分析》实验报告一学号: 1004091130 姓名:金玉琦日期:2011-11-03得分:一、实验内容:分别用蛮力法,分治法和动态规划法射击最大字段和问题的算法,比较不同算法的时间性能。
二、所用算法的基本思想及复杂度分析:1.蛮力法1)基本思想蛮力法求解最大子段和问题的设计思想很简单, 依次从第1 个数开始计算长度为1 ,2 , ⋯, n 的子段和, 将这一阶段的最大子段和保存起来, 再从第2 个数开始计算长度为1 ,2 , ⋯, n - 1 的子段和, 将这一阶段的最大子段和与前一阶段求得的最大子段和比较, 取较大者保存起来, 以此类推, 最后保存的即是整个序列的最大子段和。
2)复杂度分析时间复杂度是O(n2);2.分治法1)基本思想划分: 按照平衡子问题的原则, 将序列( a1 , a2 , ⋯, a n ) 划分成长度相同的两个子序列( a1 , ⋯, a n/ 2 ) 和( a n/ 2 + 1 , ⋯, a n ) , 则会出现以下3 种情况:① a1 , ⋯, a n 的最大子段和= a1 , ⋯, a n/ 2 的最大子段和;②a1 , ⋯, a n 的最大子段和= a n/ 2 + 1 , ⋯, a n 的最大子段和;③a1 , ⋯, a n 的最大子段和= Σjk = i a k , 且1 ≤i ≤n/ 2 , n/ 2 + 1 ≤j ≤n。
比较在划分阶段的3 种情况下的最大子段和, 取三者之中的较大者为原问题的解。
2)复杂度分析算法的时间复杂性为O( n log2 n)。
3.动态规划法1)基本思想动态规划法求解最大子段和问题的关键就在于确定动态规划函数。
求解的主要思想如下:将序列(a1,a2,……,a n)中的从第1个数字到第i个数字之间的最大子段和存入数组b[i]中,则b数组中的最大元素就是所求。
b数组求法如下:b[i-1]+a i ,b[i-1]>0b[i]=a i,b[i-1]<=02)复杂度分析动态规划的时间复杂度是O(n)三、源程序及注释:#define MAX 10000#include <IOSTREAM>#include <TIME.H>#include <WINDOWS.H>using namespace std;//蛮力法int BF_Sum(int n[],int l,int &index1,int &index2){int max=0;int sum=0;int i,j;for (i=0;i<l-1;i++){sum=n[i];for(j=i+1;j<l;j++){if(sum>=max){index1=i;index2=j;max=sum;}sum+=n[j];}}return max;}//分治法int DC_Sum(int n[],int l,int r){int sum=0,s1=0,s2=0;int lefts=0,rights=0;int leftsum=0,rightsum=0;int center;int i;if(l==r){if(n[l]>0)sum=n[l];elsesum=0;}else{center=(l+r)/2;leftsum=DC_Sum(n,l,center);rightsum=DC_Sum(n,center+1,r);for(i=center;i>=l;i--){lefts+=n[i];if(lefts>=s1) s1=lefts;}for(i=center+1;i<=r;i++){rights+=n[i];if(rights>=s2) s2=rights;}sum=s1+s2;if(sum<leftsum) sum=leftsum;if(sum<rightsum) sum=rightsum; }return sum;}//动态规划法int DY_Sum(int a[],int l){int sum=0;int *b=(int *)malloc(l*sizeof(int)); b[0]=a[0];for(int i=1;i<l;i++){if(b[i-1]>0)b[i]=b[i-1]+a[i];elseb[i]=a[i];}for(int j=0;j<l;j++)if(b[j]>sum)sum=b[j];delete []b;return sum;}void main(){int num[MAX];int i;int n;int index1,index2;LARGE_INTEGER begin,end,frequency; QueryPerformanceFrequency(&frequency);//生成随机序列//////////cout<<"输入序列大小:";cin>>n;srand(time(0));for (i=0;i<n;i++){if(rand()%2==0)num[i]=rand()/30;elsenum[i]=(-1)*rand()/30;if(n<=100)cout<<num[i]<<" ";}cout<<endl;//蛮力法//cout<<"\n蛮力法:"<<endl;cout<<"最大子段和:";QueryPerformanceCounter(&begin);cout<<BF_Sum(num,n,index1,index2)<<endl; QueryPerformanceCounter(&end);if(n<=100){cout<<"最大子段:";cout<<"从"<<num[index1]<<"到"<<num[index2]<<endl;}cout<<"时间:"<<(double)(end.QuadPart-begin.QuadPart)/frequency.QuadPart <<"s"<<endl;//分治法/////////////////////////////////////////cout<<"\n分治法:"<<endl;cout<<"最大子段和:";QueryPerformanceCounter(&begin);cout<<DC_Sum(num,0,n)<<endl;QueryPerformanceCounter(&end);cout<<"时间:"<<(double)(end.QuadPart-begin.QuadPart)/frequency.QuadPart<<"s"<<endl;//动态规划法/////////////////////////////////////cout<<"\n动态规划法:"<<endl;cout<<"最大子段和:";QueryPerformanceCounter(&begin);cout<<DY_Sum(num,n)<<endl;QueryPerformanceCounter(&end);cout<<"时间:"<<(double)(end.QuadPart-begin.QuadPart)/frequency.QuadPart<<"s"<<endl;}四、运行输出结果:五、调试和运行程序过程中产生的问题、采取的措施及获得的相关经验教训:调试过程中,蛮力法会出现计算错误。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
3
4
5
6
先序遍历 V-L-R 中序遍历 L-V-R
7 8 9 10 11
后序遍历 L-R-V
数据结构 (30230594)
14
吴及 电子工程系
分治算法的效率估计
设对于规模为n的问题,算法的时间复杂度为T(n) 采用分治法求解,设每次可以将一个实例分解成为若干个规模为
n/b的实例,其中a个实例需要求解 为简单起见,假设n=bk,则有:
持续这样处理,直至残差满足 f (c) <ε
数据结构
27
(30230594)
x1 x* x2 b
2 1
吴及 电子工程系
小球重量
如果有n个外表完全一样的小球,其中有一个小球比其它小球轻, 如何有一架天平把这个小球找出来?
采用减治法
把小球分为两堆,每堆有n/2个小球,n为奇数则多一小球
用天平比较两堆小球的重量,如果相等,多余的小球为所求
否则取较轻的一堆,继续分解
时间复杂度:T(n) = T(n/2)+ 1, 则T(n) = log2n
有无更好的方法?
数据结构 (30230594)
28
吴及 电子工程系
减治法
减一个常量: 选择排序 建一个常因子:折半查找,二分法求解非线性方程 减可变规模: 辗转相除法
数据结构 (30230594)
29
吴及 电子工程系
变治法
基本思想
是把一个求解困难的问题转换成为一个有已知解法的问题,并 且这种转换的复杂度不超过求解目标问题的算法复杂度
顺序查找
64
88
0,1,0 3,4,3 6,7,6 9,10,9
13 37
75
92
1,1,1 4,4,4 7,7,7 10,10,10
24
吴及 电子工程系
选择排序
ASORT I NGEXAMP L E 1 ASORT I NGEXAMP L E 2 AAORT I NGEXSMP L E 3 A A ER T I NGOX SMP L E 4 A A E E T I NGOX SMP L R 5 AAEEG I NTOXSMP L R 6 AAEEG I NTOXSMP L R 7 AAEEG I L TOXSMPNR 8 A A E EG I L MOX S T P NR 9 A A E EG I LMNX S T POR 10 A A E E G I L M N O S T P X R 11 A A E E G I L M N O P T S X R 12 A A E E G I L M N O P R S X T 13 A A E E G I L M N O P R S X T 14 A A E E G I L M N O P R S T X
A A E EG I LMNOPRS T X
数据结构 (30230594)
25
吴及 电子工程系
辗转相除法
求两个整数m 和n 的最大公因子
欧几里得算法,也称辗转相除法
1. 用n 去除m,将余数赋给r; 2. 将n 的值赋给m,将r 的值赋给n, 3. 如果n=0;返回m 的值作为结果,过程结束;否则,返回第一步;
e d ge
e d ge
e d ge
e d ge
e d ge
最坏时间复杂度:O(m*n),与KMP算法比较
数据结构
6
(30230594)
吴及 电子工程系
最大公因子
蛮力法求两个整数m和n的最大公因子
比较两个整数m和n的大小,不失一般性,设有m<n成立 则从2到m,逐个判断每个整数是否可以同时整除m和n,可以得到m和n的
的正确性和效率
数据结构 (30230594)
10
吴及 电子工程系
内容提要
算法设计技术
蛮力法 分治法 贪心算法 动态规划 搜索算法
数据结构
11
(30230594)
吴及 电子工程系
分治法
基本思想
把问题的一个实例分解成为属于同一问题的若干个较小规模的实例 重复这个过程直到规模较小的实例很容易求解, 求解这些规模较小的实例, 合并较小问题的解,以得到原始问题的解。
蛮力法
不采用任何技巧,基于问题的描述直接地解决问题的方法 思路直接,不考虑代价 蛮力法举例
蛮力字符串匹配 求两个整数的最大公因子 查找元素 百元买百鸡问题
数据结构 (30230594)
5
吴及 电子工程系
蛮力字符串匹配
Kn o w l e d ge i s po we r
e d ge
数据结构 (30230594)
23
吴及 电子工程系
折半查找
折半查找也称二分查找
0 1 2 3 4 5 6 7 8 9 10 5 13 19 21 37 56 64 75 80 88 92
56 l=0, r =10, m = 5
数据结构 (30230594)
19 0,4,2
80 6,10,8
5
21
握某个特定算法更重要
数据结构 (30230594)
2
吴及 电子工程系
内容提要
算法设计技术 算法优化技术 计算复杂性理论简介
数据结构 (30230594)
3
吴及 电子工程系
内容提要
算法设计技术
蛮力法 分治法 贪心算法 动态规划 搜索算法
数据结构
4
(30230594)
吴及 电子工程系
二叉树遍历是线性时间复杂度O(n) 对一个序列求和采用分治法
在很多情形下,分治法确实有效,关键在于递推式中的参数
数据结构 (30230594)
16
吴及 电子工程系
大整数乘法
两个n位整数a和b的乘法如何进行? 蛮力法:传统的计算方式
a = an an-1 …a2 a1, b = bn bn-1 …b2 b1
假设每个元素的查找概率相
等,则平均查找长度为:
n1
n1 1
n 1
ASL i0 PiCi i0 n (i 1) 2
对于规模为N的集合,平均
来说需要进行N/2次比较
数据结构 (30230594)
序号 1 2 3 4 5 6
204 205 206 207
8
学号 2002010972 2003010141 2003010142 2003010340 2003010415 2003010532
全部公因子cf1, cf2, cf13…… 这个公因子序列中最大的cfk,即为m和n的最大公因子 或者从m到2,逐个判断每个整数是否可以同时整除m和n,找到的第一个
能够同时整除m和n的整数就是最大公因子
针对蛮力法的优化 其它方法
数据结构 (30230594)
7
吴及 电子工程系
查找元素
按照蛮力法的思想,采用逐 个比较的方式
2003011327 2003080085 2003080086 2003080087
姓名 班级
林凌南 无37
姚泓毅 无34
秦文 无31
蓝青 无31
高天石 无32
陈树卫 无35
曾波 无311
阮玄清 无33
阮孟贵 无33
李炅敏 无33
吴及 电子工程系
百元买百鸡问题
百元买百鸡问题:公鸡每只5元、母鸡每只3元、小鸡3只1元,百元买百 鸡,问共有多少种买法?
分治法
子集S1和S2的划分, 时间复杂度:T(n) = 2T(n/2)+ M(n),
由于M(n)∈O(n), 因此:T(n)∈O(nlogn)
数据结构
22
(30230594)
吴及 电子工程系
减治法
减治法是把问题转化为规模较小的子问题,通过求解子问题来得 到原问题的解
对于有些问题,减治法与分治法存在一定的相关性
GI L
N PO
TX
IL
OP
T
I
P
A A E EG I LMNOPR S T X
数据结构 (30230594)
13
吴及 电子工程系
二叉树的遍历
树的遍历就是按某种次序访问树中的结点,
要求每个结点访问一次且仅访问一次。
0
设访问根结点记作 V 遍历根的左子树记作 L
1
2
遍历根的右子树记作 R
遍历方式
2010-2011春季学期数据与算法课程讲义
算法设计技术
吴及 wuji_ee@
清华大学电子工程系 2011年5月
科学研究的一般方法
客观 观察认识 数学 算法设计 算法 实验测试 结果
事物 和猜想 模型
求解
分析
反馈验证
从特定算法到算法设计的一般性技术 知道求解的方法比知道解更重要,掌握算法设计和优化技术比掌
c = a*b = a*bn* 10n-1+a*bn-1* 10n-1…a*b2* 10 +a*b1 考虑乘法的复杂度:n2次乘法
数据结构 (30230594)
17
吴及 电子工程系
大整数乘法
采用分治法
设a和b都为n位整数,则可表示为:
a = af10n/2+al,b = bf10n/2+bl af和bf分别为a和b的前半部分,al和bl分别为a和b的后半部分 c = a*b = (af * bf) 10n + (af * bl + al * bf ) 10n/2 + (al * bl)
Strassen矩阵乘法
矩阵乘法
蛮力法:需要8次乘法和4次加法
Strassen矩阵乘法
其中:
数据结构 (30230594)
20
吴及 电子工程系
Strassen矩阵乘法
Strassen矩阵乘法需要7次乘法和18次加减法 对于高维矩阵,可以引入分治法