计算几何 _ 2010 East Central Regional Contest _ problem D

来源:互联网 发布:java代码混淆工具下载 编辑:程序博客网 时间:2024/06/05 15:44

此题算做计算几何基础题。

对刚入门的挑战者而言,这题是个不错的选择。。。。

 

题目大意:

  给定一个人的坐标,在其周围有不超过100个人,此人有一个照相机(相机的拍摄视角为 f ),问此人能将其周围的每一个人至少找到一次所需的至少拍照次数。

 

分析思路:

所给人数不超过100,可以用枚举。。。

  以给定的人为坐标原点,将其周围的人分别作直线,可以得到不同倾角的直线。然后对这些直线进行排序,计算以每条直线为拍摄视角的起始边界直线所得到的拍照次数并取其中的最小值,就可以得到结果。。。

  关键:计算以每条直线为方向角的起始边界直线所得到的拍照次数

  以倾角最小的那条直线为例,从逆时针反方向看,判断遇到的直线的倾角与这条直线的倾角之差是否在 f 范围之内。如果是,说明一张照片能容得下这两个人(每条直线对应一个人);如果不是,则将拍摄视角的起始边更新为所遇到的这条边,继续进行以上判断,直到遇到的直线是最开始的那条直线为止。就可得到这一直线对应的拍摄次数。再枚举余下的所有直线的情况,去拍摄次数的最小值。。。。

 

代码实现: 

#include<iostream>#include<cmath>#include<cstdlib>#include<algorithm>#define PI 3.14159265#define eps 1e-10using namespace std;double slop[100];int n,x,y,f;void getslops(int m)          //输入点的坐标,并计算出其倾角(由斜率转换) {     double a,b;     int i;     for(i=0;i<m;i++)     {         cin>>a>>b;         slop[i]=atan2(b-y,a-x)*180/PI;         if(slop[i]<0)             slop[i]+=360.0;     }     }double orIn(double a,double b) //判断两倾角之差是否在 f 范围内 {    double c;    c=b-a;    if(c<0)        c+=360.0;    return c;}void leasttimes(int t){    int i,j;    int start,time,ans=100;    double angel;    for(i=0;i<t;i++)    {        start=i;        time=0;         angel=slop[start];        while(1)        {            time++;            //找出第i轮中 能照到所有人所需拍照的次数             start=(start+1)%t;            while(start!=i&&orIn(angel,slop[start])<=f)//               start=(start+1)%t;                      //每 f 角度范围内能照到的人             if(start==i)                break;            angel=slop[start]; //替换得到第 i 轮中另一个 f 角度范围的起点         }        if(ans>time)            ans=time;        //输出次数中的最小值    }    cout<<ans<<endl;     }int cmp(const void* a,const void* b) //double 类型的cmp函数的格式要注意 {    return ((*(double *)a-*(double *)b)>eps?1:-1);}int main(){    int temp=0;    while(cin>>n>>x>>y>>f,n||x||y||f)    {        temp++;         getslops(n);                   //计算斜率         qsort((void*)slop,n,sizeof(double),cmp); //从小到大依次排列各个倾角,且其范围均在0-360内 //      sort(slop,slop+n);        cout<<"Case "<<temp<<": ";        leasttimes(n);                //输出最少拍照次数     }    return 0;}