实验一:递归与分治
作者:互联网
一、循环赛日程安排
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