Where_Free

羸弱 无知 自大 懒惰

2019年广东外语外贸大学程序设计竞赛(新手赛)-F题(好快的刀)题解

题面:

 

 

题目意为,任意连接两个圆的圆心形成一条直线,计算与该直线相交或相切的圆的数量,求这些直线最多能相交或相切多少个圆

解题思路:

遍历所有的圆,计算出两圆圆心生成的直线,再遍历其他的圆,检测这些圆的半径与圆心到直线的距离,即可确认直线与圆的关系。

坑点:

用函数思路解决时,需考虑斜率不存在问题(用向量解决即可规避该问题)

所有圆均为同心圆时,需特判(比赛测试数据并未考虑该特殊情况,赛后由广州大学的一位大佬发现,特此感谢)

标程:

出题时分别用函数的方法和向量的方法手搓了两份代码,最后用的标程是用kuangbin模板写的

向量的方法精度比函数的方法精度要高,但为降低难度还是放宽了精度的范围(大师兄说年轻人不能太毒瘤)

 1 #include <iostream>
 2 #include <cmath>
 3 using namespace std;
 4 const double eps=1e-8;
 5 const double inf =1e20;
 6 //const double pi=acos(-1.0);
 7 int sgn(double x){
 8     if(fabs(x)<eps) return 0;
 9     if(x<0) return -1;
10     else return 1;
11 }
12 struct Point{
13     double x,y;
14     Point(){}
15     Point(double _x,double _y){
16         x=_x;
17         y=_y;
18     }
19     void input(){
20         scanf("%lf%lf",&x,&y);
21     }
22     bool operator ==(Point b)const{
23         return sgn(x-b.x)==0&&sgn(y-b.y)==0;
24     }
25     Point operator -(const Point &b)const{
26         return Point(x-b.x,y-b.y);
27     }
28     double operator ^(const Point &b)const{
29         return x*b.y-y*b.x;
30     }
31     double distance(Point p){
32         return hypot(x-p.x,y-p.y);
33     }
34 };
35 struct Line{
36     Point s,e;
37     void input(){
38         s.input();
39         e.input();
40     }
41     double length(){
42         return s.distance(e);
43     }
44     double dispointtoline(Point p){
45         return fabs((p-s)^(e-s))/length();
46     }
47 };
48 struct circle{
49     Point p;
50     double r;
51     void input(){
52         p.input();
53         scanf("%lf",&r);
54     }
55     bool operator ==(circle v){
56         return (p==v.p);
57     }
58     int relationline(Line v){
59         double dst=v.dispointtoline(p);
60         if(sgn(dst-r)<0) return 2;
61         else if(sgn(dst-r)==0) return 1;
62         else return 0;
63     }
64     
65 };
66 int main(){
67     int n,ans(2),cou,flag(0);
68     circle cir[105];
69     Line line1;
70     cin>>n;
71     for(int i=0;i<n;i++) cir[i].input();
72     for(int i=0;i<n;i++){
73         if(cir[i]==cir[0]&&i==n-1)flag=1;
74     }
75     if(flag){
76         cout<<n<<'\n';
77         return 0;
78     }
79     for(int i=0;i<n;i++){
80         for(int j=0;j<n;j++){
81             cou=2;
82             if(i==j) continue;
83             line1.e=cir[i].p;
84             line1.s=cir[j].p;
85             for(int k=0;k<n;k++){
86                 if(k==i||k==j) continue;
87                 if(cir[k].relationline(line1)!=0) cou++;
88             }
89             ans=max(ans,cou);
90         }
91     }
92     cout<<ans<<'\n';
93     return 0;
94 }

最后非常抱歉出题时没有考虑到同心圆的特殊情况,导致测试数据不够完善,特此致歉。

posted on 2019-11-23 00:25  Where_Free  阅读(274)  评论(0编辑  收藏  举报

导航