其他分享
首页 > 其他分享> > 实验一:递归与分治

实验一:递归与分治

作者:互联网

一、循环赛日程安排

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