分治法:巨人与鬼

一组n个巨人正与n个鬼进行战斗,每个巨人的武器是一个质子炮, 它可以把一串质子流射中鬼而把鬼消灭。

质子流沿直线行进,在击中鬼时就终止。巨人决定采取下述策略。他们寻找鬼配对,以形成n个巨人─鬼对,。

然后每个巨人同时向他选取的鬼射出一串质子流。我们知道,让质子流互相交叉是很危险的。

因此巨人选择的配对方式应该使质子流都不会交叉。假定每个巨人和每个鬼的位置都是平面上的一个固定点,并且没有三个位置共线, 求一种配对方案

  1 /*************************************************************************
  2     > File Name:my_jurenyugui.cpp
  3     > Author:chudongfang 
  4     > Mail:1149669942@qq.com 
  5     > Created Time: 2016年06月1日 星期三5 16时43分32秒
  6  ************************************************************************/
  7  
  8 #include<iostream>
  9 #include<stdio.h>
 10 #include<string.h>
 11 #include<math.h>
 12 #include<stdlib.h>
 13 using namespace std;
 14 typedef long long ll;
 15  
 16 typedef struct node
 17 {
 18     int id;
 19     int x;
 20     int y;
 21     int type;
 22     double angle; 
 23 }NODE;
 24 NODE p[1000];//结构体数组,用来储存每个人的信息
 25 int ans[1000];//结构,ans[i]=j代表编号i和编号为j的相连
 26 void sovel(int l,int r);
 27  
 28 int main(int argc, char const *argv[])
 29 {
 30     memset(ans,0,sizeof(ans));
 31     int x,y,t,len=1;
 32     while(scanf("%d%d%d",&t,&x,&y)!=EOF)// 录入数据 
 33     {
 34         p[len].x   =x;
 35         p[len].y   =y;
 36         p[len].id  =len;//对应ID
 37         if(t==1)
 38             p[len].type=1;//表示类型
 39         else
 40             p[len].type=-1;    
 41         len++;
 42     }        
 43     len--;
 44  
 45     sovel(1,len);
 46     
 47     for(int i=1;i<=len;i++)
 48         printf("%d ",ans[i]);
 49     return 0;
 50 }
 51  
 52 void sovel(int l,int r)//递归求解,分治思想
 53 {
 54     NODE t;
 55     if(l>=r)  return ;
 56     int pos=l;//初始化为第一个
 57     /************步骤1**************/
 58     for(int i=l+1;i<=r;i++)//找编号l-r区域内左下角节点
 59         if(p[i].y<p[pos].y||p[i].y==p[pos].y&&p[i].x<p[pos].x)
 60             pos=i;
 61  
 62     t=p[l];//交换
 63     p[l]=p[pos];
 64     p[pos]=t;
 65  
 66     int cnt=p[l].type;//从第一个开始
 67     /**************步骤2*************/
 68     for(int i=l+1;i<=r;i++)//计算点与左下角点的角度大小
 69         p[i].angle=atan2(p[i].y-p[l].y, p[i].x-p[l].x);
 70     
 71     /*for(int i=l;i<=r;i++)
 72     {
 73         printf("%d %d %d %lf
",p[i].id,p[i].x,p[i].y,p[i].angle);
 74     }*/
 75     
 76     for(int i=l+1;i<=r;i++)//按角度大小,把除左下角的元素排序
 77     {
 78         for(int j=i;j<=r;j++)
 79         {
 80             if(p[i].angle>p[j].angle)
 81             {
 82                 t=p[i];
 83                 p[i]=p[j];
 84                 p[j]=t;
 85             }
 86         }
 87     }
 88     
 89     /*for(int i=l;i<=r;i++)
 90     {
 91         printf("%d %d %d %lf
",p[i].id,p[i].x,p[i].y,p[i].angle);
 92     }*/
 93     /**************步骤3***************/
 94     for(int i=l+1;i<=r;i++)//排序后,从小到大遍历
 95     {
 96         cnt+=p[i].type;
 97         if(cnt==0)//当遍历过后的区域巨人和鬼的数量相同时
 98         {
 99             ans[p[l].id]=p[i].id;//链接左下角点和当前点
100             ans[p[i].id]=p[l].id;
101             sovel(l+1,i-1);//分治,递归求解左边区域
102             sovel(i+1,r);//分治,递归求解右边区域
103             break;
104         }
105     }
106     return ;
107 }
原文地址:https://www.cnblogs.com/aininot260/p/9643657.html