分治与递归
1.循环赛日程表安排问题
#include<stdio.h>
#include <stdlib.h>
#include <cmath>
#include <iostream>
using namespace std;
void GameTable(int k, int a[50][50])
{
int n=2;
int i, j, t, temp;
a[1][1]=1; a[1][2]=2;
a[2][1]=2; a[2][2]=1;
for (t=1; t<k; t++)
{
temp=n; n=n*2;
for(i=temp+1; i<=n; i++)
for(j=1; j<=temp; j++)
a[i][j]=a[i-temp][j]+temp;
for(i=1; i<=temp; i++)
for(j=temp+1; j<=n; j++)
a[i][j]=a[i+temp][j-temp];
for(i=temp+1;i<=n; i++)
for(j=temp+1; j<=n; j++)
a[i][j]=a[i-temp][j-temp];
}
}
void main()
{
int i,j,k;
int a[50][50];
printf("请输入比赛人数:");
scanf("%d",&k);
int m=log(k*1.0)/log(2.0);
GameTable(m,a);
for(i=1; i<=k; i++)
{
for(j=1; j<=k; j++)
printf("%5d",a[i][j]);
printf("\n");
}
system("pause");
}
2.分治算法、蛮力法,编程实现最近点对问题
#include<iostream>
#include<cmath>
using namespace std;
#define TRUE 1
#define FALSE 0
typedef struct Node //坐标
{
double x;
double y;
int order;
}Node;
int n; //点的数目
typedef struct List
{
Node* point; //点
int count; //点的个数
}List;
typedef struct CloseNode
{
Node a;
Node b;
double space; //距离平方
}CloseNode;
void create(List &L)//创建
{
cout<<"请输入平面上点的个数:\n";
cin>>n;
L.count=n;
L.point = new Node[L.count];
cout<<"输入各点坐标(x,y)"<<endl;
for(int i=0;i<L.count;++i)
{
cin>>L.point[i].x>>L.point[i].y;
L.point[i].order=i;
}
}
double square(Node a,Node b)//距离的平方
{
return ((a.x-b.x)*(a.x-b.x))+((a.y-b.y)*(a.y-b.y));
}
void BubbleSort(Node r[],int length)//排序
{
int change,n;
n=length;change=TRUE;
double b,c;
int d;
for(int i=0;i<n-1&&change;++i)
{
change=FALSE;
for(int j=0;j<n-i-1;++j)
{
if(r[j].x >r[j+1].x )
{
b=r[j].x;
c=r[j].y;
d=r[j].order;
r[j].x=r[j+1].x;
r[j].y=r[j+1].y;
r[j].order=r[j+1].order;
r[j+1].x=b;
r[j+1].y=c;
r[j+1].order=d;
change=TRUE;
}
}
}
}
void paixu(List L) //按X轴从小到大的顺序排列
{
BubbleSort(L.point,L.count);
}
//左右各距中线d的区域的最近对算法
void middle(const List & L,CloseNode &cnode,int mid,double midX)
{
int i,j; //分别表示中线左边,右边的点
double d=sqrt(cnode.space);
i=mid;
while(i>=0&&L.point[i].x>=(midX-d)) //在左边的d区域内
{
j=mid;
while(L.point[++j].x<=(midX+d)&&j<=L.count) //在右边的d区域内
{
if(L.point[j].y<(L.point[i].y-d)||L.point[j].y>(L.point[i].y+d)) //判断纵坐标是否在左边某固定点的2d区域内
continue;
double space = square(L.point[i],L.point[j]);
if(cnode.space>space) //在满足条件的区域内依次判断
{
cnode.a=L.point[i];
cnode.b=L.point[j];
cnode.space=space;
}
}
--i;
}
}
//分治法求最近对
void DivideConquer(const List &L,CloseNode &closenode,int begin,int end)
{
if(begin!=end)
{
int mid = (begin+end)/2; //排列后的中间的那个点
double midX = L.point[mid].x;
DivideConquer(L,closenode,begin,mid); //继续在左半边用分治法求最近对
DivideConquer(L,closenode,mid+1,end); //继续在右半边用分治法求最近对
middle(L,closenode,mid,midX); //判断左右各距中线d的区域,是否有最近对
}
}
void force(List list)
{
if(list.count==1)
cout<<"only one point";
if(list.count==2)
cout<<square(list.point[0],list.point[1]);
else
{
int i, j;
double mindis, temp;
Node min1,min2;
mindis = square(list.point[0],list.point[1]);
min1 = list.point[0];
min2 = list.point[1];
for (i = 0; i < list.count - 1; i++){
for (j = i + 1; j < list.count; j++){
temp = square(list.point[i],list.point[j]);
if (temp < mindis){
mindis = temp; //替换
min1 = list.point[i];
min2 = list.point[j];
}
}
}
cout<<"蛮力解法的最近点对为:"<<endl<<min1.x<<","<<min1.y<<"和"<<min2.x<<","<<min2.y<<endl;
}
}
void main()
{
//初始化
List list;
CloseNode closenode;
closenode.space = 10000; //最近点的距离
create(list); //输入各点到List中
cout<<"各点坐标为:"<<endl;
for(int i=0;i<list.count;++i)
cout<<"X"<<list.point[i].order<<"="<<list.point[i].x<<" Y"<<list.point[i].order<<"="<<list.point[i].y<<"\n";
cout<<"分治法求解:";
paixu(list);
cout<<"经过排序后的各点:"<<endl;
for(int j=0;j<list.count;++j)
cout<<"X"<<list.point[j].order<<"="<<list.point[j].x<<" Y"<<list.point[j].order<<"="<<list.point[j].y<<"\n";
DivideConquer(list,closenode,0,list.count-1);
cout<<"最近对为点 ("<<closenode.a.x<<","<<closenode.a.y<<")和点("<<closenode.b.x<<","<<closenode.b.y<<")\n";
cout<<"最近距离为: "<<sqrt(closenode.space)<<endl;
force(list);
system("pause");
}