二维凸包
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#define rin(i,a,b) for(int i=(a);i<=(b);i++)
#define rec(i,a,b) for(int i=(a);i>=(b);i--)
#define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
typedef long long LL;
using std::cin;
using std::cout;
using std::endl;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
const int MAXN=10005;
int n,sta[MAXN],top;
struct Point{
double x,y;
inline friend Point operator - (Point A,Point B){return (Point){A.x-B.x,A.y-B.y};}
}a[MAXN];
inline int cmpd(double A,double B){return fabs(A-B)<1e-8?0:(A>B)*2-1;}
inline double getdis(Point A,Point B){return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));}
typedef Point Vector;
inline double getcross(Vector A,Vector B){return A.x*B.y-A.y*B.x;}
inline bool cmpy(Point A,Point B){return cmpd(A.y,B.y)==0?cmpd(A.x,B.x)>0:cmpd(A.y,B.y)>0;}
inline bool cmppr(Point A,Point B){
double temp=getcross(A-a[1],B-a[1]);
return cmpd(temp,0)==0?cmpd(getdis(a[1],B),getdis(a[1],A))>0:cmpd(temp,0)>0;
}
int main(){
n=read();
rin(i,1,n) scanf("%lf%lf",&a[i].x,&a[i].y);
if(n==1){printf("0.00
");return 0;}
else if(n==2){printf("%.2f",getdis(a[1],a[2]));return 0;}
rin(i,2,n) if(cmpy(a[1],a[i])) std::swap(a[1],a[i]);
std::sort(a+2,a+n+1,cmppr);
top=2,sta[1]=1,sta[2]=2;
rin(i,3,n){
while(top>2&&cmpd(getcross(a[i]-a[sta[top-1]],a[i]-a[sta[top]]),0)<0) top--;
sta[++top]=i;
}
double c=0;
rin(i,2,top) c+=getdis(a[sta[i-1]],a[sta[i]]);c+=getdis(a[sta[top]],a[1]);
printf("%.2f",c);
return 0;
}
线段判交
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <iomanip>
#define rin(i,a,b) for(int i=(a);i<=(b);i++)
#define rec(i,a,b) for(int i=(a);i>=(b);i--)
#define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
typedef long long LL;
using std::cin;
using std::cout;
using std::endl;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
const int MAXN=15;
int n,ans,c[MAXN];
bool vis[MAXN];
struct Point{
double x,y;
inline friend Point operator - (Point A,Point B){return (Point){A.x-B.x,A.y-B.y};}
}a[MAXN],b[MAXN];
inline int cmpd(double A,double B){return fabs(A-B)<1e-8?0:(A>B)*2-1;}
typedef Point Vector;
inline double getdot(Vector A,Vector B){return A.x*B.x+A.y*B.y;}
inline double getcross(Vector A,Vector B){return A.x*B.y-A.y*B.x;}
inline bool onseg(Point C,Point A,Point B){return cmpd(getcross(A-C,B-C),0)==0&&cmpd(getdot(A-C,B-C),0)<0;}
inline bool dointer(Point A,Point B,Point C,Point D){
if(std::max(A.x,B.x)<std::min(C.x,D.x)||std::max(C.x,D.x)<std::min(A.x,B.x)||std::max(A.y,B.y)<std::min(C.y,D.y)||std::max(C.y,D.y)<std::min(A.y,B.y)) return 0;
double d1=getcross(C-A,B-A)*getcross(B-A,D-A),d2=getcross(A-C,D-C)*getcross(D-C,B-C);
if(cmpd(d1,0)<=0||cmpd(d2,0)<=0) return 0;
if(cmpd(d1,0)>0&&cmpd(d2,0)>0) return 1;
if(cmpd(d1,0)==0) return onseg(C,A,B)|onseg(D,A,B);
if(cmpd(d2,0)==0) return onseg(A,C,D)|onseg(B,C,D);
}
inline bool check(int pos){
if(pos<3) return 1;
rin(i,2,pos-1) if(dointer(b[i-1],b[i],b[pos-1],b[pos])) return 0;
return 1;
}
void dfs(int pos){
if(pos==n+1){b[pos]=b[1];if(check(pos)) ans++;return;}
rin(i,2,n){
if(vis[i]) continue;
b[pos]=a[i];vis[i]=1;//c[pos]=i;
if(check(pos)) dfs(pos+1);
vis[i]=0;
}
}
int main(){
while(1){
a[++n].x=read(),a[n].y=read();
if(a[n].x==0&&a[n].y==0) break;
}
b[1]=a[1];vis[1]=1;
dfs(2);
printf("%d
",ans>>1);
return 0;
}
最小圆覆盖
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#define rin(i,a,b) for(int i=(a);i<=(b);i++)
#define rec(i,a,b) for(int i=(a);i>=(b);i--)
#define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
typedef long long LL;
using std::cin;
using std::cout;
using std::endl;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
const int MAXN=500005;
int n;
double r;
struct Point{
double x,y;
}a[MAXN],o;
inline int dcmp(double A,double B){return fabs(A-B)<1e-6?0:(A>B)*2-1;}
inline double getdis(Point A,Point B){return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));}
inline Point getmid(Point A,Point B){return (Point){(A.x+B.x)/2,(A.y+B.y)/2};}
inline Point geto(Point A,Point B,Point C){
double a=B.x-A.x,b=B.y-A.y,c=C.x-A.x,d=C.y-A.y,e=((B.x*B.x-A.x*A.x)+(B.y*B.y-A.y*A.y))/2,f=((C.x*C.x-A.x*A.x)+(C.y*C.y-A.y*A.y))/2;
return (Point){(d*e-b*f)/(a*d-b*c),(c*e-a*f)/(b*c-a*d)};
}
int main(){
n=read();
rin(i,1,n) scanf("%lf%lf",&a[i].x,&a[i].y);
std::random_shuffle(a+1,a+n+1);
o=a[1],r=0;
rin(i,2,n){
if(dcmp(getdis(a[i],o),r)>0){
o=a[i],r=0;
rin(j,1,i-1){
if(dcmp(getdis(a[j],o),r)>0){
o=getmid(a[i],a[j]),r=getdis(a[i],o);
rin(k,1,j-1){
if(dcmp(getdis(a[k],o),r)>0)
o=geto(a[i],a[j],a[k]),r=getdis(a[i],o);
}
}
}
}
}
printf("%.2f %.2f %.2f
",o.x,o.y,r);
return 0;
}
半平面交
题解
旋转卡壳
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cctype>
#include <algorithm>
#define rin(i,a,b) for(int i=(a);i<=(b);i++)
#define rec(i,a,b) for(int i=(a);i>=(b);i--)
#define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
typedef long long LL;
using std::cin;
using std::cout;
using std::endl;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
const int MAXN=50005;
int n,sta[MAXN],top;
struct Po{
LL x,y;
inline friend Po operator - (Po A,Po B){return (Po){A.x-B.x,A.y-B.y};}
}p[MAXN];
inline LL getdis(Po A,Po B){return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);}
typedef Po Ve;
inline LL getcross(Ve A,Ve B){return A.x*B.y-A.y*B.x;}
inline bool cmppr(Po A,Po B){return getcross(A,B)==0?getdis(A,p[1])<getdis(B,p[1]):getcross(A,B)>0;}
int main(){
n=read();
rin(i,1,n){
p[i].x=read(),p[i].y=read();
if(p[i].y<p[1].y||(p[i].y==p[1].y&&p[i].x<p[1].x)) std::swap(p[i],p[1]);
}
rec(i,n,1) p[i].x-=p[1].x,p[i].y-=p[1].y;
std::sort(p+2,p+n+1,cmppr);
top=1,sta[1]=1;
rin(i,2,n){
while(top>1&&getcross(p[sta[top]]-p[sta[top-1]],p[i]-p[sta[top]])<=0) top--;
sta[++top]=i;
}
int ptr1=1,ptr2=2;LL ans=0;
for(;ptr1<=top;ptr1++){
int nxt1=ptr1%top+1,nxt2=ptr2%top+1;
while(getcross(p[sta[nxt1]]-p[sta[ptr1]],p[sta[ptr2]]-p[sta[ptr1]])<getcross(p[sta[nxt1]]-p[sta[ptr1]],p[sta[nxt2]]-p[sta[ptr1]])){
ptr2=nxt2;
nxt2=ptr2%top+1;
}
ans=std::max(ans,std::max(getdis(p[sta[ptr1]],p[sta[ptr2]]),getdis(p[sta[nxt1]],p[sta[ptr2]])));
}
printf("%lld
",ans);
return 0;
}