分治与递归

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");

}

posted @ 2019-06-17 08:45  夜游星  阅读(358)  评论(0编辑  收藏  举报