ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

实验一:递归与分治

2021-05-26 17:01:12  阅读:174  来源: 互联网

标签:node distances cout 递归 int 分治 选手 实验 low


一、循环赛日程安排

1、实验内容

利用分治算法,编程实现循环赛日程表安排问题,并进行时间复杂性分析;

2、实验分析

1.题目理解
(1)根据已经学得知识,8个人大循环赛需要7天。
(2)当比赛人数为2^k时,可以用分治法,多边形轮转法则可以解决一切输入
2.设计分析
(1)输出循环列表,第一列为选手编号,从第n(n>2)列开始,为第n天的比赛信息。(1,2)位置,存放的是2,则代表,在第一天,一号选手和二号选手比赛。
(2)多边形轮转法思路。当人数为奇数n时,n边形中,处在同一条水平线上的一对点一起比赛,单独一条线上的和中心点比赛。当为偶数时,将一个数放入中心点即可。
(3)代码分析,先设计好第一天的的比赛,后面的轮转做

3、程序代码

(代码多借鉴于网络)

/*循环赛日程*/
/*多边形轮转法*/
#include<iostream>
using namespace std;
int b[20];
int plan[1010][1010];
void lunzhuan(int n) {
	plan[n][1] = n;

	if(n==1) return;

	//判断奇数还是偶数,若是奇数转为偶数
	int m;
	if(n%2==1) m=n;
	else m=n-1;
	//

	for(int i=1; i<=m; i++) {
		//第1列,表示第i个选手
		plan[i][1]=i;
		//b数组用来判断同一水平线
		b[i]=b[m+i]=i+1;
	}
	int k, r;
	//轮转 ,确定那个选手和那个选手比赛
	for(int i = 1; i <= m; i++) {
		//单独一个水平线的选手与中心处选手比赛
		plan[1][i + 1] = b[i];//b[i]=i+1,例(1,2)位置放2,1号选手与2号选手在第一天比赛 
		plan[b[i]][i + 1] = 1;//(2,2)位置,2号选手与1号选手在第一天比赛 

		for(int j = 1; j <= m / 2; j++) {
			//同一水平线选手比赛
			k = b[i + j];
			r = b[i + m - j];
			plan[k][i + 1] = r;
			plan[r][i + 1] = k;
		}
	}
}
int main() {
	int n;//人数
	cout<<"请输入比赛人数"<<endl;
	cin>>n;
	lunzhuan(n);
	//打印表头
	cout<<"************"<<endl;
	cout<<"循环赛日程表"<<endl;
	cout<<"************"<<endl;
	cout<<"选手";
	for(int i=1; i<=n-1; i++)
		cout<<"\t"<<"第"<<i<<"天";
	cout<<endl;
	//
	for(int i=1; i<=n; i++) {
		for(int j=1; j<=n; j++) {
			cout<<plan[i][j]<<"\t  ";
		}

		cout<<endl;
	}
	return 0;
}

二、最近点对问题

1、实验内容

利用分治算法、蛮力法,编程实现最近点对问题,并进行时间复杂性分析。注:要求针对计算机随机生成的100点对数据,分别用蛮力法和分治法求解最近点对,对比其复杂性。

2、实验分析

2.1题目分析

同时用蛮力法和分治法实现对最近点对问题的解决,比较解决问题的时间,复杂度等。

2.2蛮力法设计

直接使用双重for循环语句,来得出最近点对之间的距离。

2.3分治法设计

(1)先将所有点按x升序排列。
(2)划分x坐标中位数
(3)左递归求解左半部分点集最小d1
(4)右递归求解右半部分点集最小d2,d1和d2取最小值
(5)依次考察集合S中的点p(x,y),如果(x<=xm 并且x>=xm-d),则将点p放入集合P1中;如果(x>xm 并且x<=xm+d),则将点p放入集合P2中;
(6)将集合P1和P2按y坐标升序排列
(7)对集合P1和P2中的每个点p(x,y),在y坐标区间[y,y+d]内最对取出6个候选点,计算与点p的最近距离d3;返回min(d,d3)

2.4运行时间对比

使用clock()函数获取时间来。在函数运行前获取一次时间,在函数运行结束后获取一次时间,两次时间做差,估计认为运行时间。为了体现时间,中间采取一个循环来加大运行时间。

2.5时间复杂度分析

(1)蛮力法采取双重循环,时间复杂度为O(n^2);
(2)分治法。当k=2时,T(n)=1,当k>2时,T(n)=2T(n/2)+n
T(n)=0(nlog2n)

2.6生成随机点

采用rand()函数,生成0-500间的数

3、程序代码

/*最近点对问题*/
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<ctime>
using namespace std;

/*定义储存结构*/
struct node{
	int x;
	int y;
}; 

/*随机生成测试点*/
void creatpoint(node s[],int num)
{
	for(int i=0;i<num;i++)
	{
		s[i].x=rand()%500;
		s[i].y=rand()%500;
	 }
	 cout<<"生成成功"<<endl; 
	 for(int i=0;i<num;i++)
	 {
	 	cout<<"("<<s[i].x<<","<<s[i].y<<")  ";
	 }
 } 
 
  /*距离求解*/
 double distances(node a,node b)
 {
 	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
 }
 
 /*按坐标升序排列*/
bool cmpx(node &a,node &b)
 {
 	return a.x<b.x;
 }
 
/*按y坐标升序排列*/
bool cmpy(node &a,node &b)
 {
 	return a.y<b.y;
 }
 
 /*分治法求解*/
 double fenzhi(node s[],int low,int high)
 {

 	//cout<<"1"<<endl;
 	double d1,d2,d3,d;
 	int mid,i,j,index;
 	node p[101];//总点集
 	node minp1,minp2;
 	if(high-low==1)
 	{
 		return distances(s[low],s[high]);
	 }
 	if(high-low==2)
 	{
 		d1=distances(s[low],s[low+1]);
 		d2=distances(s[low+1],s[high]);
 		d3=distances(s[low],s[high]);
 		if((d1<d2)&&(d1<d3))
 		return d1;
 		else if(d2<d3) return d2;
		 else return d3; 
	 }
 	mid=(low+high)/2;//计算中间点
	d1=fenzhi(s,low,mid);//递归求解左
	d2=fenzhi(s,mid+1,high);//递归求解右
	if(d1<d2) d=d1;
	else d=d2;
	index=0;
	for(i=mid;(i>=low)&&(s[mid].x-s[i].x<d);i--)//建立p1 
	{
		p[index++]=s[i];
	 } 
	for(i=mid+1;(i<=high)&&(s[i].x-s[mid].x<d);i++)//建立p2 
	{
		p[index++]=s[i];
	}
	sort(p,p+index,cmpy);//对集合p1和p2按y坐标升序排列 
	for(i=0;i<index;i++)
	{
		for(j=i+1;j<index;j++)
		{
			if(p[j].y-p[i].y>=d)
			break;
			else{
				d3=distances(p[i],p[j]);
				if(d3<d)
				{
					d=d3;
					minp1=p[i];
					minp2=p[j];
				}	
			}
		}
		return d;
	 }
	 
 }
 
/*蛮力法解决*/
 void force(node p[],int length)
 {
		int i,j;
		double min,temp;
		
		node minp1=p[0];
		node minp2=p[1];

		min=distances(p[0],p[1]);
		for(i=0;i<length-1;i++)
		{
			for(j=i+1;j<length;j++)
			{
				temp=distances(p[i],p[j]);
				if(temp<min){
					min=temp;
					minp1=p[i];
					minp2=p[j];
				}
			}
		}
		cout<<endl;
		cout<<endl; 
		cout<<"最近点对为"<<endl;
		cout<<"("<<minp1.x<<")"<<"("<<minp1.y<<")和" <<"("<<minp2.x<<")"<<"("<<minp2.y<<")"<<endl;
		cout<<"******"<<endl;
	    cout<<"蛮力法"<<endl;
		cout<<"******"<<endl;
		cout<<"最近距离为: "<<min<<endl;
		cout<<endl;
  } 

 int main()
 {
 	node s[101];
 	creatpoint(s,100);
 	
 	//蛮力法解决
 	time_t b1,e1;
 	double t1;
 	b1=clock();
 	
	force(s,100);
	
	int m=10000000;
	while(m)
	{
		m--;
	}
	e1=clock();
	t1=double(e1-b1);
	
	cout<<"运行时间 "<<t1<<"ms"<<endl; 
	//分治法 
	time_t b2,e2;
	double t2;
	b2=clock();
	cout<<"******"<<endl;
	cout<<"分治法"<<endl; 
	cout<<"******"<<endl;
 	double n;
 	sort(s,s+100,cmpx);//按x升序将点集排列 
	n=fenzhi(s,0,100);
	cout<<"最近距离为 "<<endl; 
	cout<<n<<endl;
	int k=10000000;
	while(k)
	{
		k--;
	}
	e2=clock();
	t2=double(e2-b2);
	cout<<"运行时间 "<<t2<<"ms"<<endl;
 	return 0;
 }

程序是蓝色的诗

标签:node,distances,cout,递归,int,分治,选手,实验,low
来源: https://blog.csdn.net/sxh195792/article/details/117296601

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有