实验项目1:蛮力法与分治法应用

合集下载

金块问题_实验报告

金块问题_实验报告

一、实验目的1. 理解分金块问题的背景和意义;2. 掌握分治法的基本思想及其在解决分金块问题中的应用;3. 比较不同算法在解决分金块问题时的性能;4. 提高编程能力和算法设计能力。

二、实验内容1. 问题概述分金块问题是一个经典的算法问题。

问题描述如下:老板有n个金块,希望最优秀的雇员得到其中最重要的一块,最差的雇员得到其中最轻的一块。

假设有一台比较重量轻重的天平,要求设计一个算法,在尽可能少的比较次数内,将金块分为三组,使得最优秀的雇员得到最重的金块,最差的雇员得到最轻的金块。

2. 算法分析针对分金块问题,我们可以采用以下两种算法:(1)蛮力法(非递归)蛮力法的基本思想是:遍历所有可能的分组方式,找出最优解。

具体步骤如下:① 将n个金块依次编号为1至n;② 遍历所有可能的分组方式,即从第一个金块开始,将其与其他金块进行分组,然后继续对剩余的金块进行分组,直到分组完毕;③ 对于每一种分组方式,分别找出最重的金块和最轻的金块,并比较其重量;④ 找出所有分组方式中最优的分组方式,即最重的金块和最轻的金块的重量差最小。

(2)分治法分治法的基本思想是将大问题分解为若干个小问题,递归地解决这些小问题,然后合并其结果。

具体步骤如下:① 当n=1时,直接返回该金块;② 将n个金块随机分为两组,分别编号为A和B;③ 分别对A组和B组递归调用分治法,找出每组中的最重金块和最轻金块;④ 比较A组最重金块和A组最轻金块的重量差,以及B组最重金块和B组最轻金块的重量差;⑤ 根据比较结果,确定最终的最重金块和最轻金块。

三、实验步骤1. 实验环境:Python 3.72. 实验数据:随机生成100个金块,重量在1至1000之间。

3. 实验代码(1)蛮力法实现```pythondef brute_force(n):# 初始化金块重量列表weights = [i for i in range(1, n+1)]# 遍历所有可能的分组方式for i in range(1, n//2+1):for j in range(i+1, n-i+1):for k in range(j+1, n-j+1):# 计算分组方式下的最重金块和最轻金块的重量差diff_a = max(weights[i-1:k]) - min(weights[i-1:k])diff_b = max(weights[k:n]) - min(weights[k:n])# 更新最优解if diff_a < diff_b:best_a = max(weights[i-1:k])best_b = min(weights[i-1:k]) else:best_a = max(weights[k:n]) best_b = min(weights[k:n]) return best_a, best_b# 测试n = 100print(brute_force(n))```(2)分治法实现```pythondef divide_and_conquer(weights, left, right):# 当只剩一个金块时,返回该金块if left == right:return weights[left]# 将金块分为两组mid = (left + right) // 2max_a = max(weights[left:mid])min_a = min(weights[left:mid])max_b = max(weights[mid:right+1])min_b = min(weights[mid:right+1])# 比较两组金块的重量差if max_a - min_a < max_b - min_b:return max_a, min_aelse:return max_b, min_b# 测试n = 100weights = [i for i in range(1, n+1)]print(divide_and_conquer(weights, 0, n-1))```四、实验结果与分析1. 实验结果(1)蛮力法:当n=100时,运行时间约为0.6秒;(2)分治法:当n=100时,运行时间约为0.001秒。

算法蛮力法实验报告(3篇)

算法蛮力法实验报告(3篇)

第1篇一、实验目的1. 理解蛮力法的基本概念和原理。

2. 掌握蛮力法的实现方法。

3. 分析蛮力法的优缺点及其适用场景。

4. 通过实际案例,加深对蛮力法的理解。

二、实验内容本次实验主要围绕蛮力法展开,通过以下步骤进行:1. 蛮力法的基本概念和原理- 了解蛮力法的定义:蛮力法是一种简单直接的算法设计策略,也称为暴力法、枚举法或穷举法。

- 掌握蛮力法的原理:蛮力法通过对问题涉及的所有可能情况进行逐一尝试,以找到问题的解。

2. 蛮力法的实现方法- 学习蛮力法的实现方法,包括循环结构、条件判断等。

- 通过实例,掌握蛮力法的编程实现。

3. 蛮力法的优缺点及其适用场景- 分析蛮力法的优点:简单易懂,易于实现。

- 分析蛮力法的缺点:效率低下,不适合处理大规模问题。

- 探讨蛮力法的适用场景:适用于问题规模较小、解空间有限的情况。

4. 实际案例- 以背包问题为例,演示蛮力法的应用。

- 分析背包问题中蛮力法的实现过程,以及时间复杂度。

三、实验步骤1. 设计实验环境- 选择合适的编程语言,如Python、Java等。

- 安装必要的开发工具和库。

2. 实现蛮力法- 编写蛮力法解决背包问题的代码。

- 分析代码的执行过程,确保逻辑正确。

3. 测试和验证- 使用不同规模的背包问题实例进行测试。

- 比较蛮力法与其他算法(如动态规划)的效率。

4. 分析和总结- 分析蛮力法的优缺点,以及适用场景。

- 总结实验过程中的心得体会。

四、实验结果与分析1. 蛮力法解决背包问题的代码实现```pythondef knapsack(weights, values, capacity):n = len(weights)results = []for i in range(1 << n):total_weight = 0total_value = 0for j in range(n):if i & (1 << j):total_weight += weights[j]total_value += values[j]if total_weight <= capacity:results.append((total_weight, total_value))return max(results, key=lambda x: x[1])```2. 背包问题实例测试- 实例1:`weights = [1, 2, 3], values = [1, 5, 4], capacity = 4`- 实例2:`weights = [1, 2, 3], values = [1, 5, 4], capacity = 5`3. 效率比较- 蛮力法的时间复杂度为O(2^n),其中n为物品数量。

蛮力法分治法求最近对

蛮力法分治法求最近对

实验题目设p1=(x1, y1), p2=(x2, y2), …, pn=(xn, yn)是平面上n个点构成的集合S,设计算法找出集合S中距离最近的点对。

实验目的(1)进一步掌握递归算法的设计思想以及递归程序的调试技术;(2)理解这样一个观点:分治与递归经常同时应用在算法设计之中。

实验内容(包括代码和对应的执行结果截图)#include<iostream>#include<cmath>#include <windows.h>using namespace std;typedef struct Node{//定义一个点的结构,用于表示一个点int x;int y;}Node;typedef struct NList{//定义一个表示点的集合的结构Node* data;int count;}NList;typedef struct CloseNode{//用于保存最近两个点以及这两个点之间的距离Node a;Node b;double space;}CloseNode;int max;void create(NList & L){cout<<"请输入平面上点的数目:\n";cin>>max;L.count=max;L.data = new Node[L.count];//====================动态空间分配cout<<"输入"<<L.count<<"个点坐标X,Y,以空格隔开:"<<endl;for(int i=0;i<L.count;i++)cin>>L.data[i].x>>L.data[i].y;}//求距离平方的函数double Distinguish2(Node a,Node b){return ((a.x-b.x)*(a.x-b.x))+((a.y-b.y)*(a.y-b.y));}//蛮力法求最近对void BruteForce(const NList & L,CloseNode & cnode,int begin,int end){for(int i=begin;i<=end;i++)for(int j=i+1;j<=end;j++){double space = Distinguish2(L.data[i],L.data[j]);if(space<cnode.space){cnode.a=L.data[i];cnode.b=L.data[j];cnode.space=space;}}}//归并排序void Merge(Node SR[],Node TR[],int i,int m,int n){//将有序的SR[i..m]和SR[m+1..n]归并为有序的TR[i..n]int j,k;for(j=m+1,k=i;i<=m&&j<=n;k++)if(SR[i].x<=SR[j].x) TR[k]=SR[i++];else TR[k]=SR[j++];while(i<=m) TR[k++]=SR[i++];while(j<=n) TR[k++]=SR[j++];}void Msort(Node SR[],Node TR1[],int s,int t){//将SR[s..t]归并排序为TR1[s..t]if(s==t) TR1[s]=SR[s];else{int m = (s+t)/2;Node *TR2=new Node[max];//new Node[t-s+1];//这个空间挂挂的,从s到t,这里是从0到t-sMsort(SR,TR2,s,m);Msort(SR,TR2,m+1,t);Merge(TR2,TR1,s,m,t);}}void MergeSort(NList L){Msort(L.data,L.data,0,L.count-1);}//分治法求最近对中间2d对称区的算法void Middle(const NList & L,CloseNode & cnode,int mid,int midX){int i,j;int d = sqrt(cnode.space);i=mid;while(i>=0&&L.data[i].x>=(midX-d)){j=mid;while(L.data[++j].x<=(midX+d)&&j<=L.count){//1,j++ 2<=,>=if(L.data[j].y<(L.data[i].y-d)||L.data[j].y>(L.data[i].y+d))continue;double space = Distinguish2(L.data[i],L.data[j]);if(cnode.space>space){cnode.a=L.data[i];cnode.b=L.data[j];cnode.space=space;}}i--;}}// ----------------------------------------------//分治法求最近对void DivideAndConquer(const NList &L,CloseNode & closenode,int begin,int end) {if((end-begin+1)<4) BruteForce(L,closenode,begin,end);else{int mid = (begin+end)/2;int midX = L.data[mid].x;DivideAndConquer(L,closenode,begin,mid);DivideAndConquer(L,closenode,mid+1,end);Middle(L,closenode,mid,midX);}}int main(){SYSTEMTIME sys;GetLocalTime( &sys );NList list;CloseNode closenode;closenode.space = 10000;create(list);cout<<"各点坐标为:"<<endl;for(int i=0;i<list.count;i++)cout<<"X="<<list.data[i].x<<" Y="<<list.data[i].y<<"\n";BruteForce(list,closenode,0,list.count-1);cout<<"用蛮力法求最近对:"<<endl;cout<<sys.wHour<<":"<<sys.wMinute<<":"<<sys.wMilliseconds;cout<<"最近对为点("<<closenode.a.x<<","<<closenode.a.y<<")和点("<<closenode.b.x<<","<<closenode.b.y<<")\n"<<"最近距离为: "<<sqrt(closenode.space)<<endl;cout<<sys.wHour<<":"<<sys.wMinute<<":"<<sys.wMilliseconds;cout<<"==================================================== ================"<<endl;cout<<"用分治法求最近对:"<<endl;cout<<sys.wHour<<":"<<sys.wMinute<<":"<<sys.wMilliseconds;MergeSort(list);cout<<"经过归并排序后的各点:"<<endl;for(int j=0;j<list.count;++j)cout<<"X="<<list.data[j].x<<" Y="<<list.data[j].y<<"\n";DivideAndConquer(list,closenode,0,list.count-1);cout<<"最近对为点("<<closenode.a.x<<","<<closenode.a.y<<")和点("<<closenode.b.x<<","<<closenode.b.y<<")\n"<<"最近距离为: "<<sqrt(closenode.space)<<endl;cout<<sys.wHour<<":"<<sys.wMinute<<":"<<sys.wMilliseconds;return 0;}实验结果分析由以上数据可知,分治法效率比蛮力法效率高。

蛮力法、分治法、减治法三种方法的理解和处理问题的类型的归纳

蛮力法、分治法、减治法三种方法的理解和处理问题的类型的归纳

蛮力法、分治法、减治法三种方法的理解和处理问题的类型的归纳一、蛮力法蛮力法是一种基础且直接的问题解决策略,通常用于寻找问题的答案或解决方案。

其核心理念在于,通过逐一检查所有可能的解决方案,从而找到问题的答案或找到最佳的解决方案。

在蛮力法中,我们通常需要投入较多的时间和计算资源,尤其是在面对大规模或复杂的问题时。

蛮力法的应用范围广泛,包括但不限于以下几种类型的问题:1. 排序问题:例如,对一个数组进行排序,我们可以使用蛮力法,通过比较每对元素并交换它们的位置,使得整个数组有序。

2. 查找问题:例如,在排序数组中查找一个特定的元素,我们可以使用蛮力法,逐一检查数组中的每个元素直到找到目标元素。

3. 组合与排列问题:例如,计算给定集合的所有可能排列或组合,我们可以使用蛮力法,通过逐一排列或组合所有可能的元素组合得到答案。

二、分治法分治法是一种将复杂问题分解为更小、更易于处理的子问题的方法。

通过将问题分解为独立的子问题,我们可以分别解决每个子问题,然后将这些解决方案组合起来,形成原始问题的解决方案。

这种方法在处理复杂问题时非常有效,因为它可以降低问题的复杂性,使我们可以更有效地解决问题。

分治法的应用范围广泛,包括但不限于以下几种类型的问题:1. 排序问题:例如,归并排序就是一种使用分治法的排序算法,它将一个大列表分解为两个小列表,对这两个小列表分别进行排序,然后合并它们以得到有序列表。

2. 搜索问题:例如,二分搜索是一种使用分治法的搜索算法,它将搜索空间一分为二,每次迭代都排除一半的元素,直到找到目标元素或确定元素不存在。

3. 图问题:例如,Dijkstra的算法就是一种使用分治法的图搜索算法,它将图分解为最短路径树,然后通过搜索每个子图的最短路径来解决整个图的最短路径问题。

三、减治法减治法是一种通过减少问题的规模或复杂性来解决问题的方法。

其核心理念在于,通过消除或减少问题的某些部分或特性,从而降低问题的复杂性或规模,使得问题更容易解决。

实验报告 蛮力分治动态最大字段

实验报告 蛮力分治动态最大字段

《算法设计与分析》实验报告一学号: 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.蛮力法求最近对问题:1)基本思想:分别计算每一对点之间的距离,然后找出距离最小的那一对,为了避免对同一对点计算两次距离,只考虑ji<的那些点对()j i P P,.2)复杂度分析:对于此算法,主要就是算两个点的欧几里得距离。

注意到在求欧几里得距离时,避免了求平方根操作,其原因是:如果被开方的数越小,则它的平方根也越小。

所以复杂度就是求平方,求执行次数为: nnT==;即时间复杂度为)-n)1)O(((2n)O。

(2n2.分治法求最近对问题:1)基本思想:用分治法解决最近点对问题,就是将一个问题分解两个子问题,然后递归处理子问题,然后合并。

可能两个点在每个子问题中,也可能两个点分别在两个子问题中,就这两种情况。

则基本过程为:找一条中垂线m(坐位S集合x坐标的中位数)把n个元素分成左右两部分元素,然后分别求得两边的最短距离1d ,2d ,然后取两者中的最小者记为d ,在中线两边分别取d 的距离,记录该距离范围内点的个数,中线左边有L 个元素,右边有R 个元素,分别将两边的点按y 坐标升序排列,在左边集合中每一个点,找右边集合的点,找到与之距离小于d的点,更新最短距离,直到循环结束,即可求出最短距离.2)复杂度分析:应用分治法求解含有n 个点的最近对问题,其时间复杂性可由递推式表示:)()2/(*2)(n f n T n T +=。

由以上分析:合并子问题的解的时间)1()(O n f =。

进而可得分治法求最近对问题的时间复杂度为:)log ()(2n n O n T =.三、源程序及注释:#include<iostream>#include 〈cstring 〉#include 〈cmath>#include 〈algorithm>#include<time.h>using namespace std ;#define eps 1e-8#define MAXN 10000000#define N 5000struct Point{double x,y;};Point S[N*2],S1[N],S2[N],P1[N],P2[N];double Distance(Point a,Point b){return sqrt((a。

实验项目1:蛮力法与分治法应用

实验项目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++或其他程序设计语言编写程序实现之,并设计相关的测试用例,验证程序的正确性。

最近点对问题

最近点对问题

算法分析与设计最近对问题最近对问题问题描述:在二维平面上的n 个点中,如何快速的找出最近的一对点,就是最近点对问题。

程序设计思想:1.蛮力法求最近对问题:基本思想:分别计算每一对点之间的距离,然后找出距离最小的那一对,为了避免对同一对点计算两次距离,只考虑j i <的那些点对()j i P P ,。

复杂度分析:对于此算法,主要就是算两个点的欧几里得距离。

注意到在求欧几里得距离时,避免了求平方根操作,其原因是:如果被开方的数越小,则它的平方根也越小。

所以复杂度就是求平方,求执行次数为: )()1()(2n O n n n T =-=;即时间复杂度为)(2n O 。

2.分治法求最近对问题:基本思想:用分治法解决最近点对问题,就是将一个问题分解两个子问题,然后递归处理子问题,然后合并。

可能两个点在每个子问题中,也可能两个点分别在两个子问题中,就这两种情况。

则基本过程为:找一条中垂线m (坐位S 集合x 坐标的中位数)把n 个元素分成左右两部分元素,然后分别求得两边的最短距离1d ,2d ,然后取两者中的最小者记为d ,在中线两边分别取d 的距离,记录该距离范围内点的个数,中线左边有L 个元素,右边有R 个元素,分别将两边的点按y 坐标升序排列,在左边集合中每一个点,找右边集合的点,找到与之距离小于d 的点,更新最短距离,直到循环结束,即可求出最短距离。

复杂度分析:应用分治法求解含有n 个点的最近对问题,其时间复杂性可由递推式表示:)()2/(*2)(n f n T n T +=。

由以上分析:合并子问题的解的时间)1()(O n f =。

进而可得分治法求最近对问题的时间复杂度为:)log ()(2n n O n T =。

程序代码:#include <stdio.h>#include <stdlib.h>#include <math.h>#define NUM 1000typedef struct{int x;int y;}N;double distance(N n1,N n2);double minDis(double d1,double d2);double shortestDis(N *data,int length,N *n1 , N *n2); double shortestDis(N *data,int length,N *n1 , N *n2){ int pre,last,middle,median;int i,c1num = 0,c2num = 0,j;N* dataP;N* dataL;N* CP;N* CL;N tn1,tn2;double dis1 ,dis2;// 当只有两个点时,返回最短距离,和点if(length == 2 ){double dis1 = distance(data[0],data[1]);*n1 = data[0];*n2 = data[1];return dis1;}else if(length == 3){// 当只有三个点时,返回最短距离,和点double dis1 = distance(data[0],data[1]);double dis2 = distance(data[1],data[2]);double dis3 = distance(data[0],data[2]);double temp;temp = dis1 < dis2 ? dis1:dis2;temp = temp < dis3 ? temp : dis3;if(temp == dis1){*n1 = data[0];*n2 = data[1];}else if(temp == dis2){*n1 = data[1];*n2 = data[2];}else{*n1 = data[0];*n2 = data[2];}return temp;}middle =length/2;pre = middle;last = length - pre;median = data[middle].x; // 记录中位数dataP = (N*)malloc(sizeof(N)*pre);dataL = (N*)malloc(sizeof(N)*last);CP = (N*)malloc(sizeof(N)*pre);CL = (N*)malloc(sizeof(N)*last);for( i = 0;i < pre ;i++)dataP[i] = data[i];for( i = 0; i< last;i++)dataL[i] = data[i+pre];dis1 = shortestDis(dataP , pre , n1 , n2);dis2 = shortestDis(dataL , last , &tn1 , &tn2);if(dis1 > dis2){*n1 = tn1;*n2 = tn2;}dis1 = minDis(dis1,dis2);for( i = 0; i < pre ; i++)if(dataP[i].x - median < dis1){CP[c1num++] = dataP[i];} // 将在中位数之前的区域中与中位数距离小于最短距离的点放到CP 中for( i = 0; i < last ; i++)if(median - dataL[i].x < dis1){CL[c2num++] = dataL[i];}// 将在中位数之后的区域中与中位数距离小于最短距离的点放到CL 中for(i = 0; i< c1num;i++){for( j =0; j < c2num ; j++){double temp = distance(CP[i],CL[j]);if(temp < dis1){dis1 = temp;*n1 = CP[i];*n2 = CL[j];}}}//依次计算中位数两旁的区域中,每一个点与另外一个区域中的距离,并且记录最短距离return dis1;}double distance(N n1,N n2){return sqrt((n1.x -n2.x)*(n1.x -n2.x) + (n1.y - n2.y)*(n1.y - n2.y));}double minDis(double d1,double d2){double d = d1 < d2 ? d1 : d2;return d;}// 分治法排序void MergeSort(N q[],int num,int mode){int i,nump,numl;N* qPre;N* qLast;if(num == 1 )return;if(num%2&&num != 2){numl = num/2;nump = num/2;nump++;}else{numl = num/2;nump = num/2;}qPre = (N*)malloc(sizeof(N)*nump);qLast = (N*)malloc(sizeof(N)*numl);for(i = 0;i < nump;i++)qPre[i] = q[i];for(i = 0;i<numl;i++)qLast[i] = q[nump+i];MergeSort(qPre,nump,mode);MergeSort(qLast,numl,mode);Merge(qPre,qLast,q,nump,numl,mode);}void Merge(N *pre,N *last,N *total,int nump,int numl,int mode){ int i = 0,j = 0,k = 0;while( i< nump && j< numl ){if(mode == 0){if(pre[i].x > last[j].x ){total[k++] = pre[i++];}else{total[k++] = last[j++];}}else{if(pre[i].y > last[j].y ){total[k++] = pre[i++];}else{total[k++] = last[j++];}}}if(i == nump){for(i = j; i < numl; i++)total[k++] = last[i];}else{for(j = i; j < nump; j++)total[k++] = pre[j];}}void computeShortestDistance(N* data , int num ,int result[4]){FILE *fo;int i,j,l = 0;int *datax,*datay;double dis = 666666,temp;datax = (int*)malloc(sizeof(int)*1000);datay = (int*)malloc(sizeof(int)*1000);for(i =0; i<num ;i++){datax[i] = data[i].x;datay[i] = data[i].y;}for(i = 0;i<num;i++){for(j = i+1;j<num;j++)if((temp = (datax[i] - datax[j])*(datax[i] - datax[j]) + (datay[i] - datay[j])*(datay[i] - datay[j])) < dis){dis = temp;result[0] = datax[i];result[1] = datay[i];result[2] = datax[j];result[3] = datay[j];}}printf("\n蛮力法:\n");printf("shortest dis: %f",sqrt(dis));}void generateDots(int number){FILE *fo;int i,n1,n2;if(!(fo = fopen("data.txt","w"))){printf("open file fail");exit(1);}for(i = 0;i< number;i++){srand((i*i));n1 =rand()%8000;srand(time(NULL)*i*i);n2 = rand()%6000;if(i%2)fprintf(fo,"%d %d\n",n1,n2);elsefprintf(fo,"%d %d\n",n2,n1);}fclose(fo);}int main(){ FILE* fo;N* data;int i;N n1,n2;double dis;int re[4];// 生成数据generateDots(NUM);data = (N*)malloc(sizeof(N)*1000);if(!(fo = fopen("data.txt","r"))){printf("open file fail");exit(1);}for(i = 0;i < NUM;i++){fscanf(fo,"%d %d",&data[i].x,&data[i].y);}fclose(fo);// 合并排序,排好序的数据放置到data 中。

分治法应用

分治法应用

分治法应用
分治法是一种解决问题的策略,它将一个问题分解为更小的子问题,然后分别解决这些子问题,最后将子问题的解合并以得到原问题的解。

在计算机科学和算法设计中,分治法是一种非常常见且有效的算法设计方法。

例如,在快速排序算法中,分治法被用来将一个大的数组分割成两个更小的子数组,然后递归地对这两个子数组进行排序。

这个过程一直持续到我们得到一个只有一个元素的数组,然后就可以通过比较这个元素与其相邻元素的大小来得到最终的排序结果。

在计算机图形学中,分治法也被用来解决各种问题,例如在渲染复杂的3D模型时,可以将模型分解为多个小的三角形,然后分别渲染这些三角形,最后将渲染结果合并以得到最终的图像。

此外,在数据库系统中,分治法也被用来处理大规模的数据查询。

例如,可以将一个大的数据库分解为多个小的数据库,然后分别在这些小的数据库中查找数据,最后将查找结果合并以得到最终的结果。

总的来说,分治法是一种非常有效的问题解决策略,可以用来解决各种不同领域的问题。

蛮力法、动态规划法、回溯法和分支限界法求解01背包问题

蛮力法、动态规划法、回溯法和分支限界法求解01背包问题

一、实验内容:分别用蛮力法、动态规划法、回溯法和分支限界法求解0/1背包问题。

注:0/1背包问题:给定n 种物品和一个容量为C 的背包,物品i 的重量是i w ,其价值为i v ,背包问题是如何使选择装入背包内的物品,使得装入背包中的物品的总价值最大。

其中,每种物品只有全部装入背包或不装入背包两种选择。

二、所用算法的基本思想及复杂度分析:1.蛮力法求解0/1背包问题:1)基本思想:对于有n 种可选物品的0/1背包问题,其解空间由长度为n 的0-1向量组成,可用子集数表示。

在搜索解空间树时,深度优先遍历,搜索每一个结点,无论是否可能产生最优解,都遍历至叶子结点,记录每次得到的装入总价值,然后记录遍历过的最大价值。

2)代码:#include<iostream>#include<algorithm>using namespace std;#define N 100 //最多可能物体数struct goods //物品结构体{int sign; //物品序号int w; //物品重量int p; //物品价值}a[N];bool m(goods a,goods b){return (a.p/a.w)>(b.p/b.w);}int max(int a,int b){return a<b?b:a;}int n,C,bestP=0,cp=0,cw=0;int X[N],cx[N];/*蛮力法求解0/1背包问题*/int Force(int i){if(i>n-1){if(bestP<cp&&cw+a[i].w<=C){for (int k=0;k<n;k++) X[k]=cx[k];//存储最优路径 bestP=cp;}return bestP;}cw=cw+a[i].w;cp=cp+a[i].p;cx[i]=1; //装入背包Force(i+1);cw=cw-a[i].w;cp=cp-a[i].p;cx[i]=0; //不装入背包Force(i+1);return bestP;}int KnapSack1(int n,goods a[],int C,int x[]){Force(0);return bestP;}int main(){goods b[N];printf("物品种数n: ");scanf("%d",&n); //输入物品种数printf("背包容量C: ");scanf("%d",&C); //输入背包容量for (int i=0;i<n;i++) //输入物品i 的重量w 及其价值v {printf("物品%d 的重量w[%d]及其价值v[%d]: ",i+1,i+1,i+1);scanf("%d%d",&a[i].w,&a[i].p);b[i]=a[i];}int sum1=KnapSack1(n,a,C,X);//调用蛮力法求0/1背包问题 printf("蛮力法求解0/1背包问题:\nX=[ ");for(i=0;i<n;i++)cout<<X[i]<<" ";//输出所求X[n]矩阵printf("] 装入总价值%d\n",sum1);bestP=0,cp=0,cw=0;//恢复初始化}3)复杂度分析:蛮力法求解0/1背包问题的时间复杂度为:)2()(n O n T 。

最近对蛮力分治实验报告

最近对蛮力分治实验报告

《算法设计与分析》实验报告一学号: 1004091130姓名: 金玉琦 日期: 2011-10-13得分:一、实验内容:最近对问题,即找出一个点集合中距离最近的点对,分别运用蛮力法和分治法性能解决该问题,对两种算法进行性能比较。

二、所用算法的基本思想及复杂度分析:1.分治法1)基本思想我们用分治法解决最近对问题,就是将集合S 分成两个子集S 1和S2,每个子集中有n/2个点。

然后在每个子集中递归的求其最接近的点对,在求出每个子集的最接近点对后,关键问题是如何实现分治法中的合并步骤,如果组成S 的最接近点对的2个点都在S1中或都在S2中,则问题很容易解决。

但是,如果这2个点分别在S1和S2中,则对于S1中任一点p ,S2中最多只有n/2个点与它构成最接近点对的候选者,仍需计算才能得到准确结果。

2)复杂度分析应用分治法求解含有n 个点得最近对问题,其时间复杂性可由下面的递推式表示:T (n )=2T (n /2)+f (n )合并子问题的解的时间f (n )=O (1),由通用分治递推式的主定理可得,T (n )=O (nlog 2n )2.蛮力法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 (n 2) 三、源程序及注释:#define LENGTH 10000#define min(X,Y) ((X)<(Y)?(X):(Y))#include <FLOAT.H>#include <WINDOWS.H>#include <TIME.H>#include <MATH.H>#include <algorithm>#include <IOSTREAM>using namespace std;struct point{double x;double y;};point points[LENGTH*2];// point tempLeft[LENGTH];// point tempRight[LENGTH];//排序int cmpp(point a,point b){if(a.x!=b.x) return a.x<b.x;return a.y<b.y;}//求距离的平方,在这不用求出距离,直接求出平方少计算一次,效果相同double Distence(point a,point b){return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);}//蛮力法函数double ClosestPoints(int n,point p[],int &index1,int &index2) {double minDist=DBL_MAX;double temp;for (int i=0;i<n;i++)for (int j=i+1;j<=n;j++){temp=Distence(p[i],p[j]);if(temp<minDist){minDist=temp;index1=i;index2=j;}}return sqrt(minDist);}//分治法函数double DivPoints(point p[],int begin,int end){int i,j;int n=end-begin+1;int m=(begin+end)/2;if(n==2)return Distence(p[begin],p[end]);//两个点返回距离if(n==3)//三个点直接求最近点并返回距离{double d1=Distence(p[begin],p[begin+1]);double d2=Distence(p[begin+1],p[end]);double d3=Distence(p[begin],p[end]);if(d1<=d2&&d1<=d3)return d1;else if(d2<=d3)return d2;else return d3;}double left=DivPoints(p,begin,m);double right=DivPoints(p,m+1,end);double d=min(left,right);int k,l,flag=0;//找到以m为中心的与m横坐标距离小于sqrt(d)的点for(i=begin;i<=end;i++){if(flag==0&&(p[m].x-p[i].x)<=sqrt(d)){flag=1;k=i;}if((p[i].x-p[m].x)<=sqrt(d))l=i;}for (i=k;i<=m;i++){for (j=m+1;j<=l&&fabs((p[j].y-p[i].y))<sqrt(d);j++){if(Distence(p[i],p[j])<=d)d=Distence(p[i],p[j]);}}// for(i=begin;i<=m;i++)// if((p[m].x-p[i].x)<=sqrt(d))// tempLeft[k++]=p[i]; //将m左侧与m水平距离小于d的点放入tempLeft中// for(i=m+1;i<=end;i++)// if((p[i].x-p[m].x)<=sqrt(d))// tempRight[l++]=p[i]; //将m右侧与m水平距离小于d的点放入tempRight中// //将tempLeft和tempRight按y升序排列// sort(tempLeft,tempLeft+k,cmpy);// sort(tempRight,tempRight+l,cmpy);// double md=DBL_MAX;// for(i=0;i<k;i++)// for(j=0;j<l&&fabs(tempLeft[i].y-tempRight[j].y)<=sqrt(d);j++) // {// if(Distence(tempLeft[i],tempRight[j])<=md)// md=Distence(tempLeft[i],tempRight[j]);// }return d;}//主函数void main(){LARGE_INTEGER begin,end,frequency;int n;int index1,index2;double forcedist,divdist;cout<<"输入随机点个数:";cin>>n;cout<<endl;//生成随机数srand(time(0));for (int i=0;i<n;i++){points[i].x=rand();points[i].y=rand();}//蛮力法求最近对时间QueryPerformanceFrequency(&frequency);QueryPerformanceCounter(&begin);forcedist=ClosestPoints(n,points,index1,index2);QueryPerformanceCounter(&end);cout<<"最短距离是:"<<forcedist<<"两个点是:("<<points[index1].x<<","<<points[index1].y<<")和("<<points[index2].x<<","<<points[index2].y<<")"<<endl;cout<<"蛮力法求解时间"<<(double)(end.QuadPart-begin.QuadPart)/frequency.QuadPart<<"s"<<endl;//分治法求最近对时间QueryPerformanceCounter(&begin);sort(points,points+n,cmpp); //对点对排序divdist=sqrt(DivPoints(points,0,n-1));QueryPerformanceCounter(&end);cout<<"最短距离是:"<<divdist<<endl;cout<<"分治法求解时间"<<(double)(end.QuadPart-begin.QuadPart)/frequency.QuadPart<<"s"<<endl;}四、运行输出结果:五、调试和运行程序过程中产生的问题、采取的措施及获得的相关经验教训:1在点的个数比较少的时候,蛮力法所用时间时间比分治法少,点数比较多的情况下,分治法的优势就很明显了,所用时间明显比蛮力法少。

算法设计--蛮力法 分治法求最近对问题(C++实现)

算法设计--蛮力法 分治法求最近对问题(C++实现)

算法设计--蛮力法&&分治法求最近对问题(C++实现)最近对问题?设p1=(x1,y1), p2(x2,y2), ....,pn=(xn,yn)是平面上n个点构成的集合S,最近对问题就是找出集合S中距离最近的点对。

两种算法思想:1. 蛮力法:顾名思义,利用正常的思维,使用强硬的方式求解出结果。

2. 分治法:分治,分而治之,把大问题分解为小问题,主要有三个过程:划分、求解子问题、合并。

直接上代码:蛮力法求解最近对问题:[cpp]view plaincopy1.#include "iostream"2.#include "math.h"3.#include "time.h"4.#include "stdlib.h"ing namespace std;6.struct P7.{8.int x;9.int y;10.};11.double ClosePoints(int n,P a[],int &index1,int &index2)12.{13.double d;14.double Dist=10000;15.for (int i=0;i<n-1;i++)16. {17.for (int j=i+1;j<=n-1;j++)18. {19. d=(a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y);20.if(d<=Dist)21. {22. Dist=d;23. index1=i;24. index2=j;25. }26. }27. } return Dist;28.}29.void main (void)30.{31.clock_t start,end;32.int g;33.int s,e;34. P a[10000];35.for (int i=1;i<4;i++)36. {37. cout<<"输入坐标的个数(10000以内)";38. cin>>g;39. srand(time(NULL));40.for (int r=0;r<g;r++)41. {42. a[r].x=rand()%(g-123);43. a[r].y=rand()%(g-1234);44. }45. start=clock();46.double w=ClosePoints(g,a,s,e);47. end=clock();48. cout<<"最近的两个点是:P1("<<a[s].x<<","<<a[s].y<<") P2("<<a[e].x<<","<<a[e].y<<")"<<endl; cout<<"距离是:"<<sqrt(w)<<endl;49. cout<<"蛮力法求最近对用时:"<<(double)(end-start)/CLOCKS_PER_SEC<<"ms"<<endl;50. cout<<"============================================================="<<endl;51. }52.}分治法求解最近对问题:[cpp]view plaincopy1.#include<iostream>2.#include "cstdio"3.#include "cstring"4.#include "math.h"5.#include "time.h"6.#include "stdlib.h"7.#include "algorithm"ing namespace std;9.#define eps 1e-810.#define N 1000011.//定义一个保存坐标的结构体12.struct point13.{14.double x,y;15.};16.17.point node[N * 2];18.point d[N];19.point c[N];20.point b[N];21.int cmp(point a, point b) //比较两点之间的y值22.{23.return a.y < b.y;24.}25.int cmp1(point a, point b)26.{27.if(a.x != b.x)28.return a.x < b.x;29.return a.y < b.y;30.}31.double min(double a, double b) //求a和b两者较小值32.{33.return a > b? b:a;34.}35.36.double dx(double x1, double x2)37.{38.if((x1 - x2) > eps && (x1 - x2) < eps)39. {40.return 0;41. }42.else if(x1 > x2)43. {44.return x1 - x2;45. }46.else if(x1 < x2)47. {48.return x2 - x1;49. }50.}51.52.double ds(point a, point b) //求两点之间的距离53.{54.return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));55.}56./**57.* 最近对问题58.* 三种情况:59.* 1.在子集S1中60.* 2.在自己S2中61.* 3.最近的两个点分别在子集S1和S2中62.*/63.double closestPoints(point node[], int n)64.{65.int i, j;66.int Dist = 99999; //无穷大数67.if(n < 2) //只有一个点,不存在最近对68.return 0;69.int m = (n - 1) / 2; //m是各个坐标的中位数70.for(i = m + 1; i < n; i++)71. {72. b[i].x = node[i].x;73. b[i].y = node[i].y;74. }75.//划分为两个子问题,递归求解子问题76.double d1 = closestPoints(node, m + 1); //得到S1中的最近距离d177.double d2 = closestPoints(b, n - m - 1); //得到S2中的最近距离d278.double dm = min(d1, d2); //求得d1与d2两者之间较小值79.int f,p; //记录点的个数80. p = 0;81.for(i = 0; i <= m; i++) //找出S1中与x=m的距离小于dm的所有点,保存在结构体c当中82. {83.if(dx(node[i].x,node[m].x) < dm)84. {85. c[p].x = node[i].x;86. c[p].y = node[i].y;87. p++;88. }89. }90. f=0;91.for(i = m + 1; i < n; i++) //找出S2中与x=m的距离小于dm的所有点,保存在结构题d当中92. {93.if(dx(node[i].x, node[m].x) < dm)94. {95. d[f].x = node[i].x;96. d[f].y = node[i].y;97. f++;98. }99. }100.101. sort(c, c+p,cmp); //按照y轴的坐标值升序排列102. sort(d, d+f,cmp);103.double ret = Dist;104.for(i = 0; i < p; i++) //遍历比较分别在S1和S2中两点之间的距离105. {106.for(j = 0; j < f; j++)107. {108.double ans = ds(c[i], d[j]);109. ret = min(ret, ans); //得出最近对距离110. }111. }112.return min(ret, dm); //返回第三种情形与前两种情形较小值113.}114.int main(void)115.{116.int n,i;117.for(int w=0;w<6;w++)118. {119. cout<<"输入坐标的数目:"<<endl;120. cin>>n;121. srand((unsigned)time(NULL));122.for(i=0;i<n;i++)123. {124. node[i].x=rand()/(double)(RAND_MAX/10000);125. node[i].y=rand()/(double)(RAND_MAX/10000);126. }127. sort(node,node+n,cmp);128.clock_t start,end;129. start=clock();130. closestPoints(node,n); //系统调用十次分治法函数。

蛮力法实验报告

蛮力法实验报告

数学与计算机学院实验报告一、实验项目信息项目名称:蛮力法实验实验时间: 2016/03/16 实验学时: 03 学时实验地点:工科楼503 二、实验目的及要求掌握蛮力法的设计思想,掌握蛮力法的求解步骤写程序代码,运行得到正确结果三、实验环境实验中主要使用的仪器、设备:计算机实验材料:VC6.0四、实验内容及实验步骤实验内容或原理:重复元素删除问题与荷兰国旗问题。

实验步骤:(1)录入程序代码;(2)调试程序;(3)算法正确性测试;(4)撰写实验报告重复元素删除问题:使用蛮力法求解:找出解空间:每个元素都有可能重复所以可以说解空间是数组中的每个元素遍历解空间:把每个元素和其余元素进行比较如果有重复删除程序代码:#include<stdio.h>#define N 100void deleteDuplicate(int a[]){int i,j,m;i=0;while(a[i]!=0)//遇到0的时候意味着到数组尾{j=i+1;while(a[j]!=0){if(a[i]==a[j]){printf("found duplicate\n");//若找到重复元素打印出提示m=j;while(a[m]!=0)//移动后面的数组覆盖重复元素{a[m]=a[m+1];m++;}}elsej++;}i++;}i=0;while(a[i]!=0)//打印出删除后的数组{printf("%d ",a[i]);i++;}}void main(){int a[N];int i=0;printf("Please input the number (0 to end your input!):");a[0]=10;while(i<N&&a[i]!=0){scanf("%d",&a[i]);i++;}}荷兰国旗问题:使用蛮力法求解:找出解空间遍历解空间程序代码:#include<stdio.h>#define N 20void swap_ab(int *p,int *q){int tmp=*p;*p=*q;*q=tmp;}void process(int a[],int n){int *p,*q;p=q=a;while(p!=a+n-1){if(*(p+1)<*p){q=p+1;while(*q<*(q-1)){swap_ab(q,q-1);--q;}}++p;}}void main(){int a[N],i;printf(“please input 20 numbers(0-2):”);for(i=0;i<N;i++){scanf(“%d”,&a[i]);}process(a,N);for(int i=0;i<N;i++){printf(“%d ”,a[i]);}} 五、实验结果分析重复元素删除问题:输入:5 3 5 7 7 7 8 3 0输出:5 3 7 8输入:7 8 8 6 7 9 0输出:7 8 6 9输入:2 2 1 1 5 5 3 0输出:2 1 5 3---------------------------------------------------荷兰国旗问题:(0代表R,1代表W,2代表B )输入:0 2 1 2 0 1 0 2 2 1 0 1 2 1 1 0 0 1 1 2输出:0 0 0 0 0 0 1 1 1 1 1 1 2 2 2 2 2 2输入:2 1 0 0 2 2 2 1 0 1 1 0 2 0 1 2 1 1 0 1输出:0 0 0 0 0 0 1 1 1 1 1 1 1 1 2 2 2 2 2 2输入:2 1 1 0 2 2 2 1 0 1 2 1 2 0 1 2 1 1 0 2输出:0 0 0 0 0 0 1 1 1 1 1 1 1 1 2 2 2 2 2 2六、实验总结蛮力法(也称穷举法或枚举法)是一种简单的解决问题的办法,常常直接基于问题的描述。

5算法设计技术1-蛮力法和分治法_823204234

5算法设计技术1-蛮力法和分治法_823204234
= c210n + c110n/2 + c0 其中: c2 = af * bf, c0 = al * bl ,
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)

蛮力法、动归、贪心、分支限界法解01背包问题

蛮力法、动归、贪心、分支限界法解01背包问题

算法综合实验报告一、实验内容:分别用蛮力、动态规划、贪心及分支限界法实现对0-1背包问题的求解,并至少用两个测试用例对所完成的代码进行正确性及效率关系上的验证。

二、程序设计的基本思想、原理和算法描述:1、蛮力法1.1数据结构注:结构体obj用来存放单个物品的价值和重量typedef struct obj{int w;//物品的重量int v;//物品的价值};1.2 函数组成void subset(int s[][10],int n):用来生成子集的函数void judge(int s[][10], obj obj[],int mark[],int n,int c):判断子集的可行性int getmax(int mark[],int n,int &flag):求解问题的最优解void outputObj(int flag,int s[][10],int n):输出选择物品的情况 1.3 输入/输出设计本程序通过键盘进行输入、屏幕进行输出。

1.4 符号名说明1.5 算法描述算法的伪代码描述如下:输入:背包的容量c,物品的个数n,n个物品的重量 w[n],价值v[n]输出:装入背包的物品编号以及产生的最大价值1.初始化最大价值 max=0,结果子集 s=φ;2.对集合{1,2,......n}的每一个子集T,执行下述操作:2.1初始化背包的价值 v=0,背包的重量 w=0;2.2对子集t的每一个元素j2.2.1 如果w+wj<c,则 w=w+wj,v=v+vj;2.2.2 否则,转步骤2考察下一个子集;2.3如果max<v,则 max=v;s=t;3.输出子集S中的各元素2、动态规划法2.1 数据结构该程序不涉及任何数据结构2.2 函数组成int max(int i,int j);比较并返回两个数中的较大值int KnapSack (int w[],int v[],int x[],int n,int c);求解背包取得的最大值2.3 输入/输出设计本程序通过键盘进行输入、屏幕进行输出。

TSP问题分析动态规划 分支界限法 蛮力法

TSP问题分析动态规划 分支界限法 蛮力法

算法综合实验报告学号:1004111115 姓名:李宏强一、实验内容:分别用动态规划、贪心及分支限界法实现对TSP问题(无向图)的求解,并至少用两个测试用例对所完成的代码进行正确性及效率关系上的验证。

二、程序设计的基本思想、原理和算法描述:(包括程序的数据结构、函数组成、输入/输出设计、符号名说明等)1、动态规划法(1)数据结构:①利用二进制来表示集合,则集合S可由一个十进制数x相对应,此x所对应的二进制数为y,如果y的第k位为1,则表示k存在集合S中。

例如:集合S={0,1}(其子集合为{}{0}{1}{01}),我们用二进制数11(所对应十进制数为3)表示S,11中右手边第1个数为1表示0在集合S中,右手边第二个数为1表示1在集合S中,其他位为0表示其它数字不在集合S中;同理,集合S={0,2}(其子集合为{}{0}{2}{02}可用二进制数101(所对应十进制数为5)表示(右手边第1个数为1表示0在集合S中,右手边第二个数为0表示1不在集合S中,右手边第3个数为1表示2在集合S中,则说明0,2在集合中,1不在集合中。

②利用邻接矩阵表示任意两点之间的距离例如:两点之间的距离。

j,i表示点mp[i][j](2)函数组成输入函数in()①利用动态规划法算法实现的求解函数solve() ②主函数main()③(3)输入/输出设计本程序可以通过键盘进行输入、屏幕进行输出。

(根据实际程序情况,还可以选择随机产生输入数据、将输出数据输出到文件等其它方式)这里采用随机产生输入数据,将数据输出在屏幕上的方式。

(4)符号名说明①n 表示顶点个数。

②mp[i][j] 表示顶点i和顶点j之间的距离。

③dp[i][j] 表示顶点i经过集合S(用二进制表示的数为j)后回到起始点的最短路径和。

(5)算法描述①某一个点i不经过任意点回到起始点的最短路径和为mp[i][0](默认初始点为0)dp[i][0] = mp[i][0]; (1<=i<n)②点i经过集合S(二进制表示的数为j)的最短路径和为从点i经过集合S中的某一点k后再从该点出发,经过集合S-{k}的最小值。

分别用蛮力法、分治法、减治法实现a的N次方

分别用蛮力法、分治法、减治法实现a的N次方

《算法设计与分析》实验报告一学号:姓名:日期: 2012.11.5 得分:一、实验内容:分别用蛮力法、分治法、减治法实现a^n。

二、实验要求:完成试验报告、给出对此结果。

为防止大数溢出,可以用1^n来测试在n比较大是的三种算法运行情况。

四、源程序及注释:#include <iostream>#include <windows.h>using namespace std;//蛮力法求a的n次方int Power1(int a,int n){ int as=1;for(int i=0;i<n;i++)ans*=a;return ans;//分治法求a的n次方int Power2(int a,int n){ int ans=1;if (n==0) ans=1;else if(n==1) ans=a;elseans=Power2(a,n/2)*Power2(a,(n+1)/2);return ans;}//减治法求a的n次方int Power3(int a,int n){ int ans=1;if (n==0) ans=1;else if(n==1) ans=a;else{ans=Power3(a,n/2);if(n%2==0)ans=ans*ans;//当n为偶数return ans;}int main(){int a=1;int n=10000;LARGE_INTEGER start1,end1,start2,end2,start3,end3,f;QueryPerformanceFrequency(&f);QueryPerformanceCounter(&start1) ;int p1=Power1(a,n);QueryPerformanceCounter(&end1);QueryPerformanceCounter(&start2) ;int p2=Power2(a,n);QueryPerformanceCounter(&end2);QueryPerformanceCounter(&start3) ;int p3=Power3(a,n);QueryPerformanceCounter(&end3);cout<<"a="<<a<<",n="<<n<<endl;cout<<"蛮力法求a的n次方运行时间(单位:s)及结果"<<endl<<double(end1.QuadPart-start1.QuadPart)/f.QuadPart<<" "<<p1<<endl;cout<<"分治法求a的n次方运行时间(单位:s)及结果"<<endl<<double(end2.QuadPart-start2.QuadPart)/f.QuadPart<<" "<<p2<<endl;cout<<"减治法求a的n次方运行时间(单位:s)及结果"<<endl<<double(end3.QuadPart-start3.QuadPart)/f.QuadPart<<" "<<p3<<endl;return 0;}五、运行输出结果:六、调试和运行程序过程中产生的问题、采取的措施及获得的相关经验教训:合适的代码是实验能够成功进行的关键,当然前提是对问题的深刻理解,从实验结果我们不难看出,应用减治法处理问题的效率还是很高的。

蛮力法的实验报告

蛮力法的实验报告

一、实验目的1. 理解蛮力法的基本概念和原理。

2. 掌握蛮力法的实现步骤。

3. 通过具体实例,验证蛮力法在解决实际问题中的效果和局限性。

二、实验原理蛮力法,也称为穷举法或枚举法,是一种直接基于问题描述的简单解决方法。

其基本思想是通过遍历所有可能的解空间,从中找出可行解,进而得到问题的最优解。

蛮力法的解题步骤如下:1. 找出解空间:确定问题可能的所有解的范围。

2. 遍历解空间:按照一定的顺序,逐一尝试所有可能的解。

3. 找出可行解:对每个解进行判断,确定其是否满足问题的约束条件。

4. 选取最优解:从所有可行解中,根据问题要求选择最优解。

三、实验内容本实验以“求一个三位数,个位数字比百位数字大,百位数字又比十位数字大,且各位数字之和等于各位数字相乘之积”的问题为例,采用蛮力法进行求解。

1. 解空间该问题的解空间为三位数,即100-999之间的所有整数。

2. 遍历解空间按照从100到999的顺序,逐一检查每个数是否满足以下条件:(1)个位数字比百位数字大;(2)百位数字比十位数字大;(3)各位数字之和等于各位数字相乘之积。

3. 找出可行解在遍历过程中,对于每个数,首先判断其是否为三位数。

如果是,再分别取出其百位、十位和个位数字,并判断是否满足上述条件。

4. 选取最优解由于该问题没有明确要求求解最优解,因此只需找出所有满足条件的解即可。

四、实验步骤1. 编写程序,实现蛮力法求解上述问题。

2. 运行程序,观察结果。

五、实验结果与分析1. 实验结果经过计算,发现满足条件的三位数有以下几个:- 145(1+4+5=10,1×4×5=20,不满足条件)- 261(2+6+1=9,2×6×1=12,不满足条件)- 352(3+5+2=10,3×5×2=30,不满足条件)- 463(4+6+3=13,4×6×3=72,不满足条件)- 514(5+1+4=10,5×1×4=20,不满足条件)- 625(6+2+5=13,6×2×5=60,不满足条件)- 736(7+3+6=16,7×3×6=126,不满足条件)- 847(8+4+7=19,8×4×7=224,不满足条件)- 959(9+5+9=23,9×5×9=405,不满足条件)2. 实验分析(1)蛮力法能够找到所有满足条件的解,但效率较低。

点集直径问题算法

点集直径问题算法

点集直径问题是指给定一组点,求出这组点中任意两点之间距离的最大值。

以下是解决点集直径问题的几种常见算法:
1.蛮力法:通过计算所有点对之间的距离,找到最大的距离。

时间复杂度为O(n^2),其中n是点
的数量。

这种方法简单但效率不高,特别是对于较大的点集。

2.分治法:该方法将点集分成两个子集,分别计算子集的直径,然后找到子集之间距离的最大值。

这个过程递归进行,直到子集的点数足够小,可以直接用蛮力法计算直径。

分治法的平均时间复杂度为O(nlogn),但最坏情况下可能达到O(n^2)。

3.基于哈希表的方法:该方法使用哈希表来存储每个点作为中心点时,其他点到该点的距离。

然后,
对于每个点,检查哈希表中是否存在其他点,其到当前点的距离大于当前的最大距离。

这种方法的时间复杂度为O(n^2),但常数因子较小,因此对于较小的点集可能比蛮力法更快。

4.优先队列法:该方法使用优先队列来存储距离最大的点对。

每次迭代时,从队列中删除最小距离
的点对,并计算新点对的距离。

如果新距离大于当前最大距离,则更新最大距离和队列。

这种方法的时间复杂度为O(nlogn)。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验项目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++或其他程序设计语言编写程序实现之,并设计相关的测试用例,验证程序的正确性。

测试用例要求达到30个数据以上,或程序生成100个以上的数据,验证并说明程序的正确性。

上述实验项目是一般要求,的如学生水平较高,上述这些程序已经掌握,可以设计其他难度较高问题的算法和程序。

如:hanoi 塔问题。

最后要求结合实验体会,分析算法的时间效率。

实验思考题:1、蛮力法的优缺点是什么?适用什么情况?2、分治法的基本思想是什么?适用什么情况?说明分治法的优点和局限性。

实验代码:#include<iostream>using namespace std;inline void Swap(int &x,int &y) //交换x,y{int temp=x;x=y;y=temp;}int Partition(int a[],int p,int r) //通过一趟排序将要排序的数据分割成独立的两部分//Partition 以确定一个基准元素a[q] 对子数组a[p:r]进行划分{int i=p,j=r+1;int x=a[p];//一部分的所有数据都比另外一部分的所有数据都要小while(true){while(a[++i]<x&&i<r); //将<x的元素交换到左边区域while(a[--j]>x); //将>x得元素交换到右边区域if(i>=j) break;Swap(a[i],a[j]); //交换a[i],a[j]}a[p]=a[j];a[j]=x;return j; //返回划分点}void QuickSort(int a[],int p,int r) //利用递归进行快速排序{if(p<r){int q=Partition(a,p,r); //Partition返回划分点j,此处使q=j q 为分裂点QuickSort(a,p,q-1); //对左半段排序QuickSort(a,q+1,r); //对右半段排序}}int main(){int len;cout<<"请输入数组长度: ";cin>>len;int *a=new int[len]; //动态生成一个长度为len的数组cout<<"请输入一个数组: ";for(int i=0;i<len;i++) //输入数组cin>>a[i];QuickSort(a,0,len-1); //对数组进行快排cout<<"排序后的数组是:";for(int j=0;j<len;j++)cout<<a[j]<<" "; //输出数组cout<<endl;delete[] a;return 0;}测试结果图:图1:图2:30组数据测试图:代码://递归实现合并排序#include "stdafx.h"#include <iostream>using namespace std;int a[] = {10,5,9,4,3,7,8};int b[7];template <class Type>void Merge(Type c[],Type d[],int l,int m,int r);template <class Type>void MergeSort(Type a[],int left,int right);int main(){for(int i=0; i<7; i++){cout<<a[i]<<" ";}cout<<endl;MergeSort(a,0,6);for(int i=0; i<7; i++){cout<<a[i]<<" ";}cout<<endl;}template <class Type>void Merge(Type c[],Type d[],int l,int m,int r) {int i = l,j = m + 1,k = l;while((i<=m)&&(j<=r)){if(c[i]<=c[j]){d[k++] = c[i++];}else{d[k++] = c[j++];}}if(i>m){for(int q=j; q<=r; q++){d[k++] = c[q];}}else{for(int q=i; q<=m; q++){d[k++] = c[q];}}}template <class Type>void MergeSort(Type a[],int left,int right){if(left<right){int i = (left + right)/2;MergeSort(a,left,i);MergeSort(a,i+1,right);Merge(a,b,left,i,right);//合并到数组b//复制回数组afor(int g=left; g<=right; g++){a[g] = b[g];}}}测试结果图:图1:图2:图3:30组数据测试图:分治法的基本思想:任何一个可以用计算机求解的问题所需的计算时间都与其规模N有关。

问题的规模越小,越容易直接求解,解题所需的计算时间也越少。

例如,对于n 个元素的问题,当n=1时,不需任何计算;当n=2时,只要作一次比较即可排序好;当n=3时只要做3次比较即可,…。

而当n较大时,问题就不那么容易处理了。

要想直接解决一个规模较大的问题,有时是相当困难的。

适用什么情况?分治法所能解决的问题一般具有以下几个特征:1) 该问题的规模缩小到一定的程度就可以容易地解决2) 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质。

3) 利用该问题分解出的子问题的解可以合并为该问题的解;4) 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。

上述的第一条特征是绝大多数问题都可以满足的,因为问题的计算复杂性一般是随着问题规模的增加而增加;第二条特征是应用分治法的前提它也是大多数问题可以满足的,此特征反映了递归思想的应用;第三条特征是关键,能否利用分治法完全取决于问题是否具有第三条特征,如果具备了第一条和第二条特征,而不具备第三条特征,则可以考虑用贪心法或动态规划法。

第四条特征涉及到分治法的效率,如果各子问题是不独立的则分治法要做许多不必要的工作,重复地解公共的子问题,此时虽然可用分治法,但一般用动态规划法较好。

说明分治法的优点和局限性。

优点:将待求解的问题分解成若干子问题,先求解子问题,然后再从这些子问题的解得到原问题的解;分治法中子问题相互独立。

局限性:分治法中对于每次出现的子问题均求解,导致同样的子问题被反复求解,故产生指数增长的时间复杂度,效率较低。

相关文档
最新文档