2013 ACM/ICPC Asia Regional Online —— Warmup2 E、Naive and Silly Muggles

1、这道题,我刚开始是根据三点求一三角形外接圆,然后判断点是否在圆内,其实不然,钝角三角形的时候不应该判断外接圆,而应该是以三角形最长的边为半径的圆。

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const double PI=acos(-1.0);
const double eps=1e-10;
struct Point{
 double x,y;
 Point(double x=0,double y=0):x(x),y(y){}
};
typedef Point Vector;
int dcmp(double x){
 if(fabs(x)<eps) return 0;
 else return x<0?-1:1;
}
Vector operator + (Vector A,Vector B){
 return Vector(A.x+B.x,A.y+B.y);
}
Vector operator - (Point A,Point B){
 return Vector(A.x-B.x,A.y-B.y);
}
Vector operator * (Vector A,double p){
 return Vector(A.x*p,A.y*p);
}
Point p[3],mid[2];
Vector v[2],nv[2];
Vector Rotate(Vector A,double rad){
 return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
}
double Cross(Vector A,Vector B){
 return A.x*B.y-A.y*B.x;
}
Point GetLineIntersection(Point P,Vector v,Point Q,Vector w){
 Vector u=P-Q;
 double t=Cross(w,u)/Cross(v,w);
 return P+v*t;
}
Point Center;
struct A{
 double dist;
 Point mid;
 bool operator < (const A &obj)const{
  return dcmp(dist-obj.dist)<0;
 }
}d[3];
double R1,R2,dist[3];
int T;
int main(){
 scanf("%d",&T);
 for(int kase=1;kase<=T;kase++){
  for(int i=0;i<4;i++)
   scanf("%lf%lf",&p[i].x,&p[i].y);
        d[0].dist=(p[0].x-p[1].x)*(p[0].x-p[1].x)+(p[0].y-p[1].y)*(p[0].y-p[1].y);
  d[0].mid.x=(p[0].x+p[1].x)/2;d[0].mid.y=(p[0].y+p[1].y)/2;
        d[1].dist=(p[1].x-p[2].x)*(p[1].x-p[2].x)+(p[1].y-p[2].y)*(p[1].y-p[2].y);
  d[1].mid.x=(p[1].x+p[2].x)/2;d[1].mid.y=(p[1].y+p[2].y)/2;
  d[2].dist=(p[2].x-p[0].x)*(p[2].x-p[0].x)+(p[2].y-p[0].y)*(p[2].y-p[0].y);
  d[2].mid.x=(p[2].x+p[0].x)/2;d[2].mid.y=(p[2].y+p[0].y)/2;
  sort(d,d+3);
  if(dcmp(d[0].dist+d[1].dist-d[2].dist)<0){
            R1=d[2].dist/4;
   Center.x=d[2].mid.x;Center.y=d[2].mid.y;
   R2=(Center.x-p[3].x)*(Center.x-p[3].x)+(Center.y-p[3].y)*(Center.y-p[3].y);
         if(dcmp(R2-R1)<0||dcmp(R2-R1)==0)
    printf("Case #%d: Danger\n",kase);
   else
    printf("Case #%d: Safe\n",kase);
  }else{
   v[0].x=p[1].x-p[0].x;v[0].y=p[1].y-p[0].y;
   mid[0].x=(p[1].x+p[0].x)/2;mid[0].y=(p[1].y+p[0].y)/2;
   v[1].x=p[2].x-p[1].x;v[1].y=p[2].y-p[1].y;
   mid[1].x=(p[2].x+p[1].x)/2;mid[1].y=(p[2].y+p[1].y)/2;
   nv[0]=Rotate(v[0],PI/2);
   nv[1]=Rotate(v[1],PI/2);
   Center=GetLineIntersection(mid[0],nv[0],mid[1],nv[1]);
   R1=(Center.x-p[0].x)*(Center.x-p[0].x)+(Center.y-p[0].y)*(Center.y-p[0].y);
   R2=(Center.x-p[3].x)*(Center.x-p[3].x)+(Center.y-p[3].y)*(Center.y-p[3].y);
   if(dcmp(R2-R1)<0||dcmp(R2-R1)==0)
    printf("Case #%d: Danger\n",kase);
   else
    printf("Case #%d: Safe\n",kase);
  }
    }
 return 0;
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值