結果
問題 | No.2331 Maximum Quadrilateral |
ユーザー | kotatsugame |
提出日時 | 2023-05-28 14:37:18 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 2 ms / 2,000 ms |
コード長 | 10,102 bytes |
コンパイル時間 | 1,185 ms |
コンパイル使用メモリ | 87,692 KB |
実行使用メモリ | 5,376 KB |
最終ジャッジ日時 | 2024-06-08 05:50:04 |
合計ジャッジ時間 | 2,300 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,376 KB |
testcase_02 | AC | 2 ms
5,376 KB |
testcase_03 | AC | 2 ms
5,376 KB |
testcase_04 | AC | 2 ms
5,376 KB |
testcase_05 | AC | 2 ms
5,376 KB |
testcase_06 | AC | 2 ms
5,376 KB |
testcase_07 | AC | 2 ms
5,376 KB |
testcase_08 | AC | 2 ms
5,376 KB |
testcase_09 | AC | 2 ms
5,376 KB |
testcase_10 | AC | 2 ms
5,376 KB |
testcase_11 | AC | 2 ms
5,376 KB |
testcase_12 | AC | 2 ms
5,376 KB |
testcase_13 | AC | 2 ms
5,376 KB |
testcase_14 | AC | 2 ms
5,376 KB |
testcase_15 | AC | 1 ms
5,376 KB |
testcase_16 | AC | 2 ms
5,376 KB |
testcase_17 | AC | 2 ms
5,376 KB |
testcase_18 | AC | 2 ms
5,376 KB |
testcase_19 | AC | 1 ms
5,376 KB |
testcase_20 | AC | 1 ms
5,376 KB |
testcase_21 | AC | 2 ms
5,376 KB |
testcase_22 | AC | 2 ms
5,376 KB |
testcase_23 | AC | 1 ms
5,376 KB |
testcase_24 | AC | 2 ms
5,376 KB |
testcase_25 | AC | 1 ms
5,376 KB |
testcase_26 | AC | 1 ms
5,376 KB |
testcase_27 | AC | 2 ms
5,376 KB |
testcase_28 | AC | 1 ms
5,376 KB |
testcase_29 | AC | 1 ms
5,376 KB |
testcase_30 | AC | 1 ms
5,376 KB |
testcase_31 | AC | 2 ms
5,376 KB |
testcase_32 | AC | 1 ms
5,376 KB |
testcase_33 | AC | 2 ms
5,376 KB |
testcase_34 | AC | 1 ms
5,376 KB |
testcase_35 | AC | 1 ms
5,376 KB |
testcase_36 | AC | 2 ms
5,376 KB |
testcase_37 | AC | 2 ms
5,376 KB |
testcase_38 | AC | 2 ms
5,376 KB |
testcase_39 | AC | 1 ms
5,376 KB |
testcase_40 | AC | 2 ms
5,376 KB |
testcase_41 | AC | 1 ms
5,376 KB |
testcase_42 | AC | 1 ms
5,376 KB |
testcase_43 | AC | 1 ms
5,376 KB |
testcase_44 | AC | 1 ms
5,376 KB |
testcase_45 | AC | 2 ms
5,376 KB |
testcase_46 | AC | 1 ms
5,376 KB |
ソースコード
using namespace std; #include<iostream> #include<algorithm> #include<vector> using Int=long long; int sign(Int a){return a>0?1:a<0?-1:0;} Int sqr(Int a){return a*a;} struct Rational{ Int a,b; Rational(Int a_=0):a(a_),b(1){} Rational(Int a_,Int b_){ Int g=a_,h=b_; while(h){ Int t=g%h; g=h; h=t; } a=a_/g; b=b_/g; if(b<0)a=-a,b=-b; } bool operator<(const Rational&r)const{return a*r.b<r.a*b;} bool operator==(const Rational&r)const{return a==r.a&&b==r.b;} }; struct Point{ Int x,y; Point(Int x_=0,Int y_=0):x(x_),y(y_){} Point operator-()const{return Point(-x,-y);} Point operator+(const Point&p)const{return Point(x+p.x,y+p.y);} Point operator-(const Point&p)const{return Point(x-p.x,y-p.y);} Point operator*(const Int k)const{return Point(x*k,y*k);} bool operator<(const Point&p)const{return x==p.x?y<p.y:x<p.x;} bool operator==(const Point&p)const{return x==p.x&&y==p.y;} bool operator!=(const Point&p)const{return x!=p.x||y!=p.y;} }; istream&operator>>(istream&is,Point&p){return is>>p.x>>p.y;} ostream&operator<<(ostream&os,const Point&p){return os<<p.x<<' '<<p.y;} struct Line{ Point p1,p2; Line(Point p1_=Point(),Point p2_=Point()):p1(p1_),p2(p2_){} }; struct Segment:Line{ Segment(Point p1_=Point(),Point p2_=Point()):Line(p1_,p2_){} }; struct Circle{ Point o; Int r; Circle(Point o_=Point(),Int r_=0):o(o_),r(r_){} }; using Polygon=vector<Point>; //function list begin Point vec(const Line&); Int norm(const Point&); Int norm(const Line&); int argtype(const Point&);//(-pi,0]->-1,(0,pi]->1,(0,0)->0 bool argless(const Point&,const Point&);//sorting points with arg Int dot(const Point&,const Point&); Int cross(const Point&,const Point&); enum{ONLINE_FRONT=-2,CLOCKWISE=-1,ON_SEGMENT=0,COUNTER_CLOCKWISE=1,ONLINE_BACK=2}; int ccw(const Point&,const Point&); int ccw(const Point&,const Point&,const Point&); int ccw(const Line&,const Point&); bool orthogonal(const Point&,const Point&); bool orthogonal(const Line&,const Line&); bool parallel(const Point&,const Point&); bool parallel(const Line&,const Line&); bool intersect(const Line&,const Point&); bool intersect(const Line&,const Line&); bool intersect(const Segment&,const Point&); bool intersect(const Segment&,const Segment&); bool intersect(const Line&,const Segment&); bool intersect(const Segment&,const Line&); bool intersect(const Circle&,const Point&); int intersect(const Circle&,const Line&);//overflow, count contacts int intersect(const Circle&,const Segment&);//overflow, count contacts bool intersect(const Circle&,const Circle&); int count_tangent(const Circle&,const Circle&);//count common tangents Int distance2(const Point&,const Point&); Rational distance2(const Line&,const Point&); Rational distance2(const Line&,const Line&); Rational distance2(const Segment&,const Point&); Rational distance2(const Segment&,const Segment&); Rational distance2(const Line&,const Segment&); Rational distance2(const Segment&,const Line&); bool is_convex(const Polygon&); Polygon convex_hull(Polygon,bool=false); enum{OUT,ON,IN}; int contain(const Polygon&,const Point&); int contain(const Circle&,const Point&); int contain(const Circle&,const Segment&); int convex_contain(const Polygon&,const Point&);//O(log |P|) Int diameter2(Polygon P); //function list end Point vec(const Line&s){return s.p2-s.p1;} Int norm(const Point&p){return p.x*p.x+p.y*p.y;} Int norm(const Line&s){return norm(vec(s));} int argtype(const Point&a){return a.y<0?-1:a.y>0?1:a.x<0?1:a.x>0?-1:0;} bool argless(const Point&a,const Point&b) { int at=argtype(a),bt=argtype(b); return at!=bt?at<bt:ccw(a,b)>0; } Int dot(const Point&a,const Point&b){return a.x*b.x+a.y*b.y;} Int cross(const Point&a,const Point&b){return a.x*b.y-a.y*b.x;} int ccw(const Point&a,const Point&b) { Int crs=cross(a,b); return crs>0?COUNTER_CLOCKWISE :crs<0?CLOCKWISE :dot(a,b)<0?ONLINE_BACK :norm(a)<norm(b)?ONLINE_FRONT :ON_SEGMENT; } int ccw(const Point&a,const Point&b,const Point&c){return ccw(b-a,c-a);} int ccw(const Line&s,const Point&p){return ccw(s.p1,s.p2,p);} bool orthogonal(const Point&a,const Point&b){return dot(a,b)==0;} bool orthogonal(const Line&s,const Line&t){return orthogonal(vec(s),vec(t));} bool parallel(const Point&a,const Point&b){return cross(a,b)==0;} bool parallel(const Line&s,const Line&t){return parallel(vec(s),vec(t));} bool intersect(const Line&s,const Point&p){return cross(vec(s),p-s.p1)==0;} bool intersect(const Line&s,const Line&t){return !parallel(s,t)||intersect(s,t.p1);} bool intersect(const Segment&s,const Point&p){return ccw(s,p)==ON_SEGMENT;} bool intersect(const Segment&s,const Segment&t){ return ccw(s,t.p1)*ccw(s,t.p2)<=0&&ccw(t,s.p1)*ccw(t,s.p2)<=0; } bool intersect(const Line&s,const Segment&t){ return sign(cross(vec(s),t.p1-s.p1))*sign(cross(vec(s),t.p2-s.p1))<=0; } bool intersect(const Segment&s,const Line&t){return intersect(t,s);} bool intersect(const Circle&c,const Point&p){return distance2(c.o,p)==sqr(c.r);} int intersect(const Circle&c,const Line&s){ Rational r=distance2(s,c.o); return r.a==r.b*sqr(c.r)?1:r.a<r.b*sqr(c.r)?2:0; } int intersect(const Circle&c,const Segment&s){ Int d1=distance2(c.o,s.p1),d2=distance2(c.o,s.p2); int t=intersect(c,Line(s)); return t==0?0 :d1<sqr(c.r)&&d2<sqr(c.r)?0 :(d1<sqr(c.r)&&d2>=sqr(c.r))||(d1>=sqr(c.r)&&d2<sqr(c.r))?1 :dot(s.p2-s.p1,c.o-s.p1)>=0&&dot(s.p1-s.p2,c.o-s.p2)>=0?t==1?1:2 :0; } bool intersect(const Circle&a,const Circle&b){ int c=count_tangent(a,b); return 1<=c&&c<=3; } int count_tangent(const Circle&a,const Circle&b){ Int d=distance2(a.o,b.o); return d==sqr(a.r+b.r)?3:d>sqr(a.r+b.r)?4:d==sqr(a.r-b.r)?1:d>sqr(a.r-b.r)?2:0; } Int distance2(const Point&a,const Point&b){return norm(a-b);} Rational distance2(const Line&s,const Point&p){ Int A=(s.p2.y-s.p1.y)*p.x+(s.p1.x-s.p2.x)*p.y-s.p1.x*s.p2.y+s.p1.y*s.p2.x; Int B=norm(s); return Rational(A*A,B); } Rational distance2(const Line&s,const Line&t){ return intersect(s,t)?Rational(0):distance2(s,t.p1); } Rational distance2(const Segment&s,const Point&p){ return dot(vec(s),p-s.p1)<0?Rational(distance2(p,s.p1)) :dot(-vec(s),p-s.p2)<0?Rational(distance2(p,s.p2)) :distance2(Line(s),p); } Rational distance2(const Segment&s,const Segment&t){ return intersect(s,t)?Rational(0):min({ distance2(s,t.p1),distance2(s,t.p2), distance2(t,s.p1),distance2(t,s.p2) }); } Rational distance2(const Line&s,const Segment&t){ return intersect(s,t)?Rational(0):min(distance2(s,t.p1),distance2(s,t.p2)); } Rational distance2(const Segment&s,const Line&t){return distance2(t,s);} bool is_convex(const Polygon&P){ for(int i=0;i<P.size();i++) if(ccw(P[i],P[(i+1)%P.size()],P[(i+2)%P.size()])==CLOCKWISE)return false; return true; } Polygon convex_hull(Polygon P,bool ONSEG){ if(P.size()<=2)return P; sort(P.begin(),P.end()); Polygon ret(2*P.size()); int k=0,t; if(ONSEG){ for(const Point&p:P){ while(k>=2&&ccw(ret[k-2],ret[k-1],p)==CLOCKWISE)k--; ret[k++]=p; } t=k; for(int i=P.size()-2;i>=0;i--){ while(k>=t+1&&ccw(ret[k-2],ret[k-1],P[i])==CLOCKWISE)k--; ret[k++]=P[i]; } } else{ for(const Point&p:P){ while(k>=2&&ccw(ret[k-2],ret[k-1],p)!=COUNTER_CLOCKWISE)k--; ret[k++]=p; } t=k; for(int i=P.size()-2;i>=0;i--){ while(k>=t+1&&ccw(ret[k-2],ret[k-1],P[i])!=COUNTER_CLOCKWISE)k--; ret[k++]=P[i]; } } ret.resize(k-1); int mi=0; for(int i=1;i<k-1;i++) if(ret[mi].y==ret[i].y?ret[mi].x>ret[i].x:ret[mi].y>ret[i].y)mi=i; rotate(ret.begin(),ret.begin()+mi,ret.end()); return ret; } int contain(const Polygon&P,const Point&p){ bool in=false; for(int i=0;i<P.size();i++){ Segment s(P[i],P[(i+1)%P.size()]); if(intersect(s,p))return ON; else{ Point a=s.p1-p,b=s.p2-p; if(a.y>b.y)swap(a,b); if(a.y<=0&&0<b.y&&cross(a,b)>0)in=!in; } } return in?IN:OUT; } int contain(const Circle&c,const Point&p){ Int d=distance2(c.o,p); return d==sqr(c.r)?ON:d<sqr(c.r)?IN:OUT; } int contain(const Circle&c,const Segment&s){ Int d1=distance2(c.o,s.p1),d2=distance2(c.o,s.p2); return d1<=sqr(c.r)&&d2<=sqr(c.r)?d1==sqr(c.r)||d2==sqr(c.r)?ON:IN:OUT; } int convex_contain(const Polygon&P,const Point&p) { if(P[0]==p)return ON; int l=0,r=P.size(); while(r-l>1) { int mid=(l+r)/2; int t=ccw(P[0],P[mid],p); if(t==CLOCKWISE)r=mid; else l=mid; } if(r==1)return OUT; if(l+1==P.size()) { if(intersect(Segment(P[0],P[P.size()-1]),p))return ON; else return OUT; } if(l==1&&intersect(Segment(P[0],P[1]),p))return ON; Polygon tmp={P[0],P[l],P[l+1]}; int ret=contain(tmp,p); if(ret==ON) { if(intersect(Segment(P[l],P[l+1]),p))return ON; else return IN; } return ret; } Int diameter2(Polygon P){ if(!is_convex(P))P=convex_hull(P); int mi=0,Mi=0; for(int i=1;i<P.size();i++){ if(P[i].x<P[mi].x)mi=i; if(P[i].x>P[Mi].x)Mi=i; } Int ret=0; int sm=mi,sM=Mi; while(mi!=sM||Mi!=sm){ ret=max(ret,norm(P[mi]-P[Mi])); if(cross(P[(mi+1)%P.size()]-P[mi],P[(Mi+1)%P.size()]-P[Mi])<0)mi=(mi+1)%P.size(); else Mi=(Mi+1)%P.size(); } return ret; } Int area2(Polygon P) { Int ret=0; for(int i=0;i<P.size();i++)ret+=cross(P[i],P[(i+1)%P.size()]); return ret; } #include<cassert> int N; Int C[400][400]; Int dp[3][400]; int main() { cin>>N; Polygon PP(N); for(int i=0;i<N;i++)cin>>PP[i]; Polygon P=convex_hull(PP); N=P.size(); if(N<4) { assert(N==3); Int ans=-1e18; for(int i=0;i<PP.size();i++)if(PP[i]!=P[0]&&PP[i]!=P[1]&&PP[i]!=P[2]) { { Polygon tmp=(Polygon){P[0],P[1],P[2],PP[i]}; ans=max(ans,area2(tmp)); } { Polygon tmp={P[0],P[1],PP[i],P[2]}; ans=max(ans,area2(tmp)); } { Polygon tmp={P[0],PP[i],P[1],P[2]}; ans=max(ans,area2(tmp)); } } cout<<ans<<endl; return 0; } assert(N>=4); for(int i=0;i<N;i++)for(int j=0;j<N;j++)C[i][j]=cross(P[i],P[j]); Int ans=-1e18; for(int s=0;s<N;s++) { for(int t=s+1;t<N;t++)dp[0][t]=C[s][t]; for(int k=0;k<2;k++) { for(int j=s+1;j<N;j++)dp[k+1][j]=-1e18; for(int i=s+1;i<N;i++)for(int j=i+1;j<N;j++) { dp[k+1][j]=max(dp[k+1][j],dp[k][i]+C[i][j]); } } for(int i=s+1;i<N;i++)ans=max(ans,dp[2][i]+C[i][s]); } cout<<ans<<endl; }