Codeforces 935C Fifa and Fafa 题解 附平面几何基础:平面向量基本运算

一路过去好像平面向量也是必学的知识,毕竟用初中知识解题的日子已经过去了.我们来看一个例题.
Codeforces 935C Fifa and Fafa
这个题是求一个圆之中不覆盖某点(x,y)的最大圆的圆心坐标和半径.(在圆上算不覆盖)
思路:首先判断某点是不是在圆外,如果在圆外直接输出圆的各项数值.
如果不是,很明显就是找出该点p与圆心连线延长线与圆的交点q,然后输出pq中点坐标和pq距离的一半.
如何求q点坐标?我用初中算法来做,坑了我40多分钟推公式,还wa了一次.

#include<bits/stdc++.h>
#define db double
using namespace std;
typedef long long ll;
typedef pair<db,db> pdd;
db r,x8,y8,x9,y9;

db dist(db a,db b,db c,db d)//两点之间距离
{
return sqrt((a-c)*(a-c)+(b-d)*(b-d));
}

pdd erci(db a,db b,db c)//解二次方程,用一个pair储存两个根
{
db delta=b*b-4*a*c,x1,x2;
x1=(-b+sqrt(delta))/(2*a),x2=(-b-sqrt(delta))/(2*a);
return pdd(x1,x2);
}

int main()
{
cin>>r>>x8>>y8>>x9>>y9;//由于y0,y1等会与保留字重复,所以用y8,y9,不影响观看.
db d=dist(x8,y8,x9,y9);
if (d>=r) return printf("%.15lf %.15lf %.15lf",x8,y8,r),0;//判断是否在圆外
db dis=d+r,k,b;
if (x8==x9) printf("%.15lf %.15lf %.15lf",x8,y9-dis/2,dis/2);//因为是初中算法,要特判一下横坐标相等,否则算不出k
else 
  {
  k=(y9-y8)/(x9-x8),b=y8-k*x8;//算出解析式
  pdd p=erci(1+k*k,2*k*b-2*x8-2*k*y8,x8*x8+b*b-2*b*y8+y8*y8-r*r);//20分钟一个二次方程,差点错了,利用q在直线上且与圆心O距离为r列出该方程.
  db xp,yp;
  xp=x9<x8?p.first:p.second,yp=xp*k+b;//q必须是离某点较远的那个
  xp=(xp+x9)/2,yp=(yp+y9)/2;
  printf("%.15lf %.15lf %.15lf",xp,yp,dis/2);
  }
}

坑爹吧.所以我们需要救星——平面向量!
见证奇迹的时候到了.具体的东西多看看数学书啊.(叉乘????)

//打不出向量符号简直麻烦死了.
#pragma GCC optimize("inline,Ofast",3)//优化
#define nico puts("niconiconi")//不同的人不同的debug
#include<bits/stdc++.h>
using namespace std;
const double pi=3.141592653587,eps=1e-10;
struct xl{//定义结构体向量,含有一对坐标(x,y)
double x,y;xl(){x=0,y=0;}
void read1(){scanf("%lf%lf",&x,&y);}//第一种直接读入
void read2()//第二种读入两对坐标,求差.
  {
  double a,b;
  scanf("%lf%lf%lf%lf",&x,&y,&a,&b);
  x=a-x,y=a-y;
  }
void print(){printf("%lf %lf",x,y);}//输出
double mo(){return sqrt(x*x+y*y);}//求它的模
};
xl operator -(xl a){xl b;b.x=-a.x,b.y=-a.y;return b;}//负的向量就是两个值均为相反数
xl operator +(xl a,xl b){xl c;c.x=a.x+b.x,c.y=a.y+b.y;return c;}//加法
xl operator -(xl a,xl b){return a+-b;}//减法就是加上负的向量
xl operator *(xl a,double b){xl c;c.x=a.x*b,c.y=a.y*b;return c;}//向量的数乘
double operator *(xl a,xl b){return a.x*b.x+a.y*b.y;}//向量的数量积
double jiao(xl a,xl b){return acos(a*b/a.mo()/b.mo());}//夹角
double cross(xl a,xl b){return a.x*b.y-a.y*b.x;}//叉乘结果的模
int operator ==(xl a,xl b){return fabs(a.x-b.x)<=eps&&fabs(a.y-b.y)<=eps;}//判断两向量是否相等
double mianji(xl a,xl b,xl c){return fabs(cross(b-a,c-a))/2;}//三点构成三角形面积
xl zhuan(xl a,double du){xl b;b.x=a.x*cos(du)-a.y*sin(du),b.y=a.x*sin(du)+a.y*cos(du);return b;}//将向量a逆时针转一个角度(弧度)
int shx(xl a,xl b,xl p){if (a.x<b.x) swap(a,b);double ans=cross(p-a,b-a);return abs(ans)<=eps?0:ans>0?1:-1;}//返回点p在直线ab的位置,在ab上返回0,在上方返回1,下方返回-1.
int main()
{

}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值