题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1043
题目大意:一个2000*2000方格坐标,x,y范围都是【-1000,1000】。现在给你一个圆弧,告诉你圆弧的两个端点和任意一个中间点。现在要你算出最小的矩形(长和宽都要为整数,即四个顶点在方格顶点上)来完全覆盖这个圆弧。
算法思路:很明显要算出圆心,这个可以有线段中垂线交求,也可以由方程,只是很麻烦。然后以圆心找出这个圆的左右上下四个极点,判断是否在圆弧上(用叉积即可),与给出的三个点一起维护这段圆弧的四个方向的极大点。然后向上向下取整即可。
代码:
#include<cstdio> #include<iostream> #include<algorithm> #include<cmath> #include<cstring> using namespace std; const double eps = 1e-3; const double INF = 1000000000.00; struct Point{ double x,y; Point(double x=0,double y=0): x(x), y(y) {} }; typedef Point Vector; Vector operator + (Vector A,Vector B) { return Vector(A.x+B.x,A.y+B.y); } Vector operator - (Vector A,Vector 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); } Vector operator / (Vector A,double p) { return Vector(A.x/p,A.y/p); } bool operator < (const Point& A, const Point& B){ return A.x < B.x || (A.x == B.x && A.y < B.y); } int dcmp(double x){ if(fabs(x) < eps) return 0; return x < 0 ? -1 : 1; } bool operator == (const Point& A,const Point& B){ return dcmp(A.x-B.x) == 0 && dcmp(A.y-B.y) == 0; } double Dot(Vector A,Vector B){ return A.x*B.x+A.y*B.y; } double Length(Vector A) { return sqrt(Dot(A,A)); } double Cross(Vector A,Vector B) { return A.x*B.y-A.y*B.x; } Point read_point() { Point P; scanf("%lf %lf",&P.x,&P.y); return P; } Point normal(Vector A) { return Vector(-A.y,A.x); }; Point GetLineIntersecion(Point P, Vector v,Point Q,Vector w){ Vector u = P - Q; double t = Cross(w,u)/Cross(v,w); return P + v*t; } void Judge(Point& Pl,Point& Pr,Point& Pu,Point& Pd,Point P){ if(Pl.x > P.x) Pl = P; if(Pr.x < P.x) Pr = P; if(Pu.y < P.y) Pu = P; if(Pd.y > P.y) Pd = P; } int main() { //freopen("E:\acm\input.txt","r",stdin); Point Ps,Pt,Pi; Ps = read_point(); Pt = read_point(); Pi = read_point(); Point mid1,mid2,O; mid1 = (Ps+Pi)/2; mid2 = (Pi+Pt)/2; O = GetLineIntersecion(mid1,normal(Ps-Pi),mid2,normal(Pi-Pt)); double r = Length(O-Ps); Point Pu,Pl,Pr,Pd; Pu = Pl = Pr = Pd = Ps; Judge(Pl,Pr,Pu,Pd,Pt); Judge(Pl,Pr,Pu,Pd,Pi); Point P = Point(O.x+r,O.y); if(dcmp(Cross(Pt-Ps,Pi-Ps)*Cross(Pt-Ps,P-Ps)) > 0){ Judge(Pl,Pr,Pu,Pd,P); } P = Point(O.x-r,O.y); if(dcmp(Cross(Pt-Ps,Pi-Ps)*Cross(Pt-Ps,P-Ps)) > 0){ Judge(Pl,Pr,Pu,Pd,P); } P = Point(O.x,O.y+r); if(dcmp(Cross(Pt-Ps,Pi-Ps)*Cross(Pt-Ps,P-Ps)) > 0){ Judge(Pl,Pr,Pu,Pd,P); } P = Point(O.x,O.y-r); if(dcmp(Cross(Pt-Ps,Pi-Ps)*Cross(Pt-Ps,P-Ps)) > 0){ Judge(Pl,Pr,Pu,Pd,P); } int width = ceil(Pu.y-eps) - floor(Pd.y+eps); int length = ceil(Pr.x-eps) - floor(Pl.x+eps); printf("%d ",width*length); }