QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#679921 | #9434. Italian Cuisine | rerebornzhou | RE | 0ms | 0kb | C++20 | 5.1kb | 2024-10-26 19:12:36 | 2024-10-26 19:12:37 |
answer
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define IOS std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
typedef pair<int,int> pii;
const int N=3e5+10;
const double pi = acos(-1.0); //圆周率,精确到15位小数
const double eps = 1e-8; //浮点数偏差值
int sgn(double x){ //判断与0的大小关系
if(fabs(x)<eps) return 0;
return x<0?-1:1;
}
int dcmp(double x,double y){ //判断两个浮点数的大小关系
if(fabs(x-y)<eps) return 0;
else return x<y?-1:1;
}
struct Point{
double x,y;
Point(){}
Point(double x,double y):x(x),y(y){}
Point(Point a,Point b){ //向量
x=b.x-a.x, y=b.y-a.y;
}
Point operator + (Point B){ return Point(x+B.x,y+B.y); }
Point operator - (Point B){ return Point(x-B.x,y-B.y); }
Point operator * (double k){ return Point(x*k,y*k); } //向量与实数的乘法
Point operator / (double k){ return Point(x/k,y/k); } //向量与实数的除法
bool operator == (Point B){ return sgn(x-B.x)==0 && sgn(y-B.y==0); } //两个向量判等
};
// 以下向量相关
typedef Point Vector; //用点的数据结构来表示向量
double Cross(Vector A,Vector B){ return A.x*B.y - A.y*B.x; } //向量叉积,有正负
//以下线相关
struct Line{
Point p1,p2; //直线上两点
Line(){}
Line(Point p1,Point p2):p1(p1),p2(p2){}
Line(Point p,double angle){ //根据一个点和倾斜角确定直线,0<=angle<pi
p1=p;
if(sgn(angle-pi/2)==0) { p2 = (p1 + Point(0,1));} //tan(pi/2)不存在
else { p2 = (p1 + Point(1,tan(angle)));}
}
Line(double a,double b,double c){ //ax+by+c=0
if(sgn(a)==0){
p1 = Point(0,-c/b);
p2 = Point(1,-c/b);
}
else if(sgn(b)==0){
p1 = Point(-c/b,0);
p2 = Point(-c/b,1);
}
else{
p1 = Point(0,-c/b);
p2 = Point(1,(-c-a)/b);
}
}
};
double Distance_point(Point A,Point B){ return hypot(A.x-B.x,A.y-B.y); } //两点之间的距离
double Dis_point_line(Point p,Line v){ //点到直线的距离
// cout<<p.x<<" "<<p.y<<" ["<<v.p1.x<<" "<<v.p1.y<<"] "<<" ["<<v.p2.x<<" "<<v.p2.y<<"] \n";
// cout<<fabs((double)Cross(p-v.p1,v.p2-v.p1))/Distance_point(v.p1,v.p2)<<"\n";
return fabs((double)Cross(p-v.p1,v.p2-v.p1))/Distance_point(v.p1,v.p2);
}
struct Circle{ //圆的定义
Point c; //圆心
double r; //半径
Circle(){}
Circle(Point c,double r):c(c),r(r){}
Circle(double x,double y,double r):c(Point(x,y)),r(r){}
};
int Line_circle_relation(Line v,Circle C){
double dst = Dis_point_line(C.c,v);
if(dst < C.r) return 0; //0:直线和圆香蕉
if(dst - C.r==0) return 1; //1:直线和圆相切
return 2; //2:直线在圆外
}
Point st[N];
Point p[N];
void solve(){
int n;
cin>>n;
int cx,cy,R;
cin>>cx>>cy>>R;
Circle C(Point(cx,cy),R);
vector<Point> P;
for(int i=1;i<=n;i++){
int x,y;
cin>>x>>y;
p[i].x=x;
p[i].y=y;
P.push_back(Point(x,y));
}
int top=0;
auto Andrew = [&]{
sort(p+1,p+1+n,[](Point a,Point b){ //排序
if(a.x==b.x) return a.y<b.y;
return a.x<b.x;
});
for(int i=1;i<=n;i++){ //求下凸包,<0
while(top>1 && Cross(Vector(st[top-1],st[top]), Vector(st[top-1],p[i]))<=0 ) top--;
st[++top]=p[i];
}
int t=top; //记录现在的栈顶
for(int i=n-1;i>=1;i--){ //求上凸包,也是<0,号节点一定是凸包,不用再算
while(top>t && Cross(Vector(st[top-1],st[top]), Vector(st[top-1],p[i]))<=0 ) top--;
//注意top>t条件,防止把n号节点弹出
st[++top]=p[i];
}
//凸包的起始点在在头尾存了两次
double res=0; //本题求凸包的周长
for(int i=1;i<top;i++) res+=Distance_point(st[i],st[i+1]);
return res;
};
P.clear();
Andrew();
for(int i=1;i<top;i++){
P.push_back(st[i]);
}
for(int i=0;i<n;i++){
P.push_back(P[i]);
}
auto check = [&](int i,int mid) -> bool {
if(Cross(Vector(P[mid].x-P[i].x,P[mid].y-P[i].y),Vector(C.c.x-P[mid].x,C.c.y-P[mid].y))<0){
return 0;
}
if(Line_circle_relation(Line(P[i],P[mid]),C)==0){
return 0;
}
return 1;
};
int r=0;
int area=0;
int maxn=0;
// check(0,2);
n=P.size();
for(int l=0;l<n;l++){
while(check(l,r+1)){
area-=Cross(P[r],P[l]);
area+=Cross(P[r],P[r+1]);
area+=Cross(P[r+1],P[l]);
r++;
}
// cout<<l<<" "<<r<<" "<<area<<"\n";
maxn=max(abs(area),maxn);
area-=Cross(P[r],P[l]);
area-=Cross(P[l],P[l+1]);
area+=Cross(P[r],P[l+1]);
}
cout<<maxn<<"\n";
}
signed main(){
int T=1;
cin>>T;
while(T--){
solve();
}
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 0
Runtime Error
input:
3 5 1 1 1 0 0 1 0 5 0 3 3 0 5 6 2 4 1 2 0 4 0 6 3 4 6 2 6 0 3 4 3 3 1 3 0 6 3 3 6 0 3