上的是汕头市队赛的题面
区别只有数据范围和输出
C 秀恩爱 SRM 06
背景&&描述
输入格式
第一行三个整数,n,sx,sy。n表示多边形的顶点数。
接下来n行每行俩整数,分别表示多边形一个顶点的横纵坐标。
(顶点是按照顺时针或者逆时针顺序给出的,并且所有点的坐标绝对值<=,保证不存在共线的三个顶点)
输出格式
一个整数,表示面积四舍五入为整数的结果。
样例输入
3 0 0 0 1 -1 2 1 2
样例输出
13
数据范围与约定
- 对于100%的数据:
样例解释
一道想明白就不难的题
但是有很多卡点
很明显发现扫的面积是一个大圆减去小圆
刚开始很容易误以为大圆的半径就是离圆心最远的顶点,小圆的半径就是离圆心最近的
交上去就WA了
刚开始一直想不明白为啥
后来随手造了几组数据就发现了
离圆心最近的点可能不是顶点
而是到边的垂线段的端点
接下来就是数学了
求出那个点到圆心的距离
这个大家可以去学习高中人教版数学必修二(捂脸)
但是一个大坑点:斜率为0!!!
还好我写完随手造了几个数据发现判掉了
这告诉我们写完代码随手造几个小数据手算是一个多么好的习惯
之前一直没有养成
以后一定要这样
然而———我还是WA了
其他人都是没有判除0
我虽然判了但是并没有什么卵用(一脸不爽)
因为我前面算两点距离是爆int了
哇啊啊啊啊啊
多少次爆intWA了啊
怎么就不吸取教训啊
以后看见乘法一定要注意开longlong啊(哭唧唧)
最后还有一个坑点是π的精度
开太低不行
计算器上有
大家可以抄过来
#include<cstdio>
#include<cmath>
const double pie=3.14159265358979323846264338327950288419716939937510,eps=1e-10;
struct node
{int x,y;
}e[100007];
int main()
{int n;long long sx,sy;scanf("%d %lld %lld",&n,&sx,&sy);long long p,q;double min=2*1e14,max=0;int prex,prey;for(int i=1;i<=n;i++){scanf("%lld %lld",&p,&q);e[i].x=p,e[i].y=q;double dis=(p-sx)*(p-sx)+ (q-sy)*(q-sy);if(dis>max) max=dis;if(dis<min) min=dis;}prex=e[n].x;prey=e[n].y;for(int i=1;i<=n;i++){p=e[i].x,q=e[i].y;if(p-prex==0){double tar=p,tary=sy;if(tary-(prey>q?prey:q)<=eps&& tary-(prey<q?prey:q)>=eps ){double dis=(tar-sx)*(tar-sx)+ (tary-sy)*(tary-sy);if(dis<min)min=dis;}}else if(q-prey==0){double tar=sx,tary=q;if(tar-(prex>p?prex:p)<=eps&& tar-(prex<p?prex:p)>=eps ) {double dis=(tar-sx)*(tar-sx)+ (tary-sy)*(tary-sy);if(dis<min) min=dis;}}else{double xie=(q-prey)*1.0/(p-prex);double xie2=-1.0/xie;double b2=(double)sy-xie2*sx;double b1=(double)q-xie*p;double tar=(b2-b1)/(xie-xie2);if(tar-(prex>p?prex:p)<=eps&& tar-(prex<p?prex:p)>=eps ) {double tary=xie2*tar+b2;double dis=(tar-sx)*(tar-sx)+ (tary-sy)*(tary-sy);if(dis<min)min=dis;}}prex=p,prey=q;}double k=pie*(max-min);printf("%.12lf",k);return 0;
}