计算几何把几个模板写好,然后根据不同题目分析即可。
必要代码:
const double eps=1e-8; const double PI=acos(-1.0); typedef double lf; int sgn(double x) { if(fabs(x)<eps) return 0; if(x<0) return -1; else return 1; }
二维平面上的点:
struct vec{ lf x,y; vec(lf x=0,lf y=0):x(x),y(y){} vec operator-(const vec &b){return vec(x-b.x,y-b.y);} vec operator+(const vec &b){return vec(x+b.x,y+b.y);} vec operator*(lf k){return vec(k*x,k*y);} lf operator ^(const vec &b){return x*b.y-y*b.x;} lf len(){return hypot(x,y);} lf sqr(){return x*x+y*y;} /*截取*/vec trunc(lf k=1){return *this*(k/len());} /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);} }q[maxn],pp; lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;}; lf cross(vec a,vec b,vec c){return cross(a-b,b-c);} lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;} bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);} bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);} /*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';}
判断两条线段是否相交
bool judge(vec a,vec b,vec c,vec d){ //线段ab和线段cd #define SJ(x) max(a.x,b.x)<min(c.x,d.x) || max(c.x,d.x)<min(a.x,b.x) if(SJ(x) || SJ(y))return 0; #define SJ2(a,b,c,d) cross(a-b,a-c)*cross(a-b,a-d)<=0 return SJ2(a,b,c,d) && SJ2(c,d,a,b); }
判断线段与直线是否相交
bool judge(vec a,vec b,vec c,vec d) { return sgn(cross(d,a,b))*sgn(cross(c,a,b))<=0; }
POJ - 2318
二分+叉积寻找位置即可
#include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<ctime> #include<cctype> #include<iostream> #include<algorithm> //#include<chrono> #include<vector> #include<list> #include<queue> #include<string> #include<set> #include<map> //#include<unordered_set> //#include<unordered_map> #define debug frelimiten("r.txt","r",stdin) #define mp make_pair #define ri register int using namespace std; typedef long long ll; typedef double lf; typedef pair<int, int> pii; const int maxn = 10500+10; const int INF = 0x3f3f3f3f; const int mod = 998244353; inline ll read(){ll s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s*w;} ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;} struct vec{ lf x,y; vec(lf x=0,lf y=0):x(x),y(y){} vec operator-(const vec &b){return vec(x-b.x,y-b.y);} vec operator+(const vec &b){return vec(x+b.x,y+b.y);} vec operator*(lf k){return vec(k*x,k*y);} lf len(){return hypot(x,y);} lf sqr(){return x*x+y*y;} /*截取*/vec trunc(lf k=1){return *this*(k/len());} /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);} }a[maxn],pp; lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;}; lf cross(vec a,vec b,vec c){return cross(a-b,b-c);} lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;} bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);} bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);} /*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';} int vis[maxn],n,m,i,x1,y1,x2,y2,x,y,u,l; int main() { while (~scanf("%d",&n)) { if (n==0) break; //scanf("%d%d%d%d%d",&m,&x1,&y1,&x2,&y2); memset(vis,0,sizeof(vis)); m=read(),x1=read(),y1=read(),x2=read(),y2=read(); for (i=0;i<n;i++) { scanf("%d%d",&u,&l); a[i]=vec(u,y1); a[i+n+1]=vec(l,y2); } a[n]=vec(x2,y1),a[2*n+1]=vec(x2,y2); for (i=1;i<=m;i++) { x=read(),y=read(); pp=vec(x,y); int ll=0,rr=n; int tmp=0; while (ll<=rr) { int mid=(ll+rr)>>1; if (cross(pp,a[mid],a[mid+n+1])<0) { rr=mid-1; tmp=mid; } else ll=mid+1; } vis[tmp]++; //vis[rr]++; } for (i=0;i<=n;i++) { cout<<i<<": "<<vis[i]<<endl; } cout<<endl; } return 0; }
POJ - 2398
与上一题相同,只需多个排序
#include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<ctime> #include<cctype> #include<iostream> #include<algorithm> //#include<chrono> #include<vector> #include<list> #include<queue> #include<string> #include<set> #include<map> //#include<unordered_set> //#include<unordered_map> #define debug frelimiten("r.txt","r",stdin) #define mp make_pair #define ri register int using namespace std; typedef long long ll; typedef double lf; typedef pair<int, int> pii; const int maxn = 10500+10; const int INF = 0x3f3f3f3f; const int mod = 998244353; inline ll read(){ll s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s*w;} ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;} struct vec{ lf x,y; vec(lf x=0,lf y=0):x(x),y(y){} vec operator-(const vec &b){return vec(x-b.x,y-b.y);} vec operator+(const vec &b){return vec(x+b.x,y+b.y);} vec operator*(lf k){return vec(k*x,k*y);} lf len(){return hypot(x,y);} lf sqr(){return x*x+y*y;} /*截取*/vec trunc(lf k=1){return *this*(k/len());} /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);} }pp; struct node { vec s,t; }a[maxn]; lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;}; lf cross(vec a,vec b,vec c){return cross(a-b,b-c);} lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;} bool cmp_xy(const node &a,const node &b){return make_pair(a.s.x,a.s.y)<make_pair(b.s.x,b.s.y);} bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);} /*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';} int vis[maxn],ans[maxn],n,m,i,x1,y1,x2,y2,x,y,u,l; int main() { while (~scanf("%d",&n)) { if (n==0) break; //scanf("%d%d%d%d%d",&m,&x1,&y1,&x2,&y2); memset(vis,0,sizeof(vis)); memset(ans,0,sizeof(ans)); m=read(),x1=read(),y1=read(),x2=read(),y2=read(); for (i=0;i<n;i++) { scanf("%d%d",&u,&l); a[i].s=vec(u,y1); a[i].t=vec(l,y2); } a[n].s=vec(x2,y1),a[n].t=vec(x2,y2); sort(a,a+n+1,cmp_xy); for (i=1;i<=m;i++) { x=read(),y=read(); pp=vec(x,y); int ll=0,rr=n; int tmp=0; while (ll<=rr) { int mid=(ll+rr)>>1; if (cross(pp,a[mid].s,a[mid].t)<0) { rr=mid-1; tmp=mid; } else ll=mid+1; } vis[tmp]++; } for (i=0;i<=n;i++) { if (vis[i]>0) ans[vis[i]]++; } cout<<"Box"<<endl; for (i=1;i<=n;i++) { if (ans[i]>0) cout<<i<<": "<<ans[i]<<endl; } } return 0; }
※POJ - 3304
看了证明才懂这题的思路:
1:把问题转化为是否存在一条直线与每条线段都有交点。证明:若存在一条直线l和所有线段相交,作一条直线m和l垂直,则m就是题中要求的直线,所有线段投影的一个公共点即为垂足。
2:枚举两两线段的各一个端点,连一条直线,再判断剩下的线段是否都和这条直线有交点。证明:若有l和所有线段相交,则可保持l和所有线段相交,左右平移l到和某一线段交于端点停止(“移不动了”)。然后绕这个交点旋转。也是转到“转不动了”(和另一线段交于其一个端点)为止。这样就找到了一个新的l满足题意,而且经过其中两线段的端点。
#include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<ctime> #include<cctype> #include<iostream> #include<algorithm> //#include<chrono> #include<vector> #include<list> #include<queue> #include<string> #include<set> #include<map> //#include<unordered_set> //#include<unordered_map> #define debug frelimiten("r.txt","r",stdin) #define mp make_pair #define ri register int using namespace std; typedef long long ll; typedef double lf; typedef pair<int, int> pii; const int maxn = 10500+10; const int INF = 0x3f3f3f3f; const int mod = 998244353; const double eps=1e-8; const double PI=acos(-1.0); inline ll read(){ll s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s*w;} ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;} int sgn(double x) { if(fabs(x)<eps) return 0; if(x<0) return -1; else return 1; } struct vec{ lf x,y; vec(lf x=0,lf y=0):x(x),y(y){} vec operator-(const vec &b){return vec(x-b.x,y-b.y);} vec operator+(const vec &b){return vec(x+b.x,y+b.y);} vec operator*(lf k){return vec(k*x,k*y);} // lf operator *(const vec &b){return x*b.x + y*b.y;} lf operator ^(const vec &b){return x*b.y-y*b.x;} lf len(){return hypot(x,y);} lf sqr(){return x*x+y*y;} /*截取*/vec trunc(lf k=1){return *this*(k/len());} /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);} }; struct Line { vec s,t; }a[maxn]; lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;}; lf cross(vec a,vec b,vec c){return cross(a-b,b-c);} lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;} bool cmp_xy(const Line &a,const Line &b){return make_pair(a.s.x,a.s.y)<make_pair(b.s.x,b.s.y);} bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);} /*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';} //double xmult(vec p0,vec p1,vec p2) //{ // return (p1-p0)^(p2-p0); //} double dist(vec a,vec b) { return sqrt(dot(b-a,b-a)); } bool judge(vec a,vec b,vec c,vec d){ return sgn(cross(d,a,b))*sgn(cross(c,a,b))<=0; } bool flag; int t,i,n,j; double xx,yy; bool check(vec x,vec y,int n) { if (sgn(dist(x,y)==0)) return false; for (ri k=1;k<=n;k++) if (!judge(x,y,a[k].s,a[k].t)) return false; return true; } int main() { t=read(); while (t--) { n=read(); for (i=1;i<=n;i++) { scanf("%lf%lf",&xx,&yy); a[i].s=vec(xx,yy); scanf("%lf%lf",&xx,&yy); a[i].t=vec(xx,yy); } flag=false; for (i=1;i<=n&&!flag;i++) for (j=1;j<=n&&!flag;j++) { if (check(a[i].s,a[j].t,n) || check(a[i].s,a[j].s,n) || check(a[i].t,a[j].t,n) || check(a[i].t,a[j].s,n)) { flag=true; break; } } if (flag) printf("Yes! "); else printf("No! "); } return 0; }
POJ - 1556
首先肯定要贴着点走,这时只需一个个离散每个点的位置,求一遍最短路即可。
#include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<ctime> #include<cctype> #include<iostream> #include<algorithm> //#include<chrono> #include<vector> #include<list> #include<queue> #include<string> #include<set> #include<map> //#include<unordered_set> //#include<unordered_map> #define debug frelimiten("r.txt","r",stdin) #define mp make_pair #define ri register int using namespace std; typedef long long ll; typedef double lf; typedef pair<int, int> pii; const int maxn = 10500+10; const int INF = 0x3f3f3f3f; const int mod = 998244353; const double eps=1e-8; const double PI=acos(-1.0); inline ll read(){ll s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s*w;} ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;} int sgn(double x) { if(fabs(x)<eps) return 0; if(x<0) return -1; else return 1; } struct vec{ lf x,y; vec(lf x=0,lf y=0):x(x),y(y){} vec operator-(const vec &b){return vec(x-b.x,y-b.y);} vec operator+(const vec &b){return vec(x+b.x,y+b.y);} vec operator*(lf k){return vec(k*x,k*y);} lf operator ^(const vec &b){return x*b.y-y-b.x;} lf len(){return hypot(x,y);} lf sqr(){return x*x+y*y;} /*截取*/vec trunc(lf k=1){return *this*(k/len());} /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);} }b[maxn]; lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;}; lf cross(vec a,vec b,vec c){return cross(a-b,b-c);} lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;} bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);} bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);} /*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';} double dist(vec a,vec b) { return sqrt(dot((a-b),(a-b))); } bool judge(vec a,vec b,vec c,vec d){ //线段ab和线段cd #define SJ(x) max(a.x,b.x)<min(c.x,d.x) || max(c.x,d.x)<min(a.x,b.x) if(SJ(x) || SJ(y))return 0; #define SJ2(a,b,c,d) cross(a-b,a-c)*cross(a-b,a-d)<=0 return SJ2(a,b,c,d) && SJ2(c,d,a,b); } int n,i,j,k; double x,y1,y2,y3,y4,dis[505][505]; bool flag; int main() { while (~scanf("%d",&n)) { if (n==-1) break; b[0]=vec(0,5); for (i=0;i<n;i++) { scanf("%lf",&x); scanf("%lf%lf%lf%lf",&y1,&y2,&y3,&y4); b[i*4+1]=vec(x,y1); b[i*4+2]=vec(x,y2); b[i*4+3]=vec(x,y3); b[i*4+4]=vec(x,y4); } b[n*4+1]=vec(10,5); memset(dis,0,sizeof(dis)); for (i=0;i<=4*n+1;i++) for (j=i+1;j<=4*n+1;j++) { int xx=(i-1)/4; int yy=(j-1)/4; if (i==0) xx=-1; flag=true; for (k=xx+1;k<yy;k++) { if (judge(b[4*k+1],vec(b[4*k+1].x,0),b[i],b[j])) { flag=false; break; } if (judge(b[4*k+2],b[4*k+3],b[i],b[j])) { flag=false; break; } if (judge(b[4*k+4],vec(b[4*k+4].x,10),b[i],b[j])) { flag=false; break; } } dis[i][j]=(flag?dist(b[i],b[j]):INF); dis[j][i]=dis[i][j]; } for (k=0;k<=4*n+1;k++) for (i=0;i<=4*n+1;i++) for (j=0;j<=4*n+1;j++) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); printf("%.2f ", dis[0][4 * n + 1]); } return 0; }
POJ - 2653
求线段与线段相交
#include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<ctime> #include<cctype> #include<iostream> #include<algorithm> //#include<chrono> #include<vector> #include<list> #include<queue> #include<string> #include<set> #include<map> //#include<unordered_set> //#include<unordered_map> #define debug frelimiten("r.txt","r",stdin) #define mp make_pair #define ri register int using namespace std; typedef long long ll; typedef double lf; typedef pair<int, int> pii; const int maxn = 100500+10; const int INF = 0x3f3f3f3f; const int mod = 998244353; const double eps=1e-8; const double PI=acos(-1.0); inline ll read(){ll s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s*w;} ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;} int sgn(double x) { if(fabs(x)<eps) return 0; if(x<0) return -1; else return 1; } struct vec{ lf x,y; vec(lf x=0,lf y=0):x(x),y(y){} vec operator-(const vec &b){return vec(x-b.x,y-b.y);} vec operator+(const vec &b){return vec(x+b.x,y+b.y);} vec operator*(lf k){return vec(k*x,k*y);} lf operator ^(const vec &b){return x*b.y-y-b.x;} lf len(){return hypot(x,y);} lf sqr(){return x*x+y*y;} /*截取*/vec trunc(lf k=1){return *this*(k/len());} /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);} }b[maxn]; lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;}; lf cross(vec a,vec b,vec c){return cross(a-b,b-c);} lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;} bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);} bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);} /*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';} bool judge(vec a,vec b,vec c,vec d){ //线段ab和线段cd #define SJ(x) max(a.x,b.x)<min(c.x,d.x) || max(c.x,d.x)<min(a.x,b.x) if(SJ(x) || SJ(y))return 0; #define SJ2(a,b,c,d) cross(a-b,a-c)*cross(a-b,a-d)<=0 return SJ2(a,b,c,d) && SJ2(c,d,a,b); } struct Line { vec s,t; }a[maxn]; int n,i,j,num; bool vis[maxn],flag,firstt; double x1,y1,x2,y2; int main() { while (~scanf("%d",&n)) { if (n==0) return 0; for (i=1;i<=n;i++) { scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); a[i].s=vec(x1,y1); a[i].t=vec(x2,y2); } memset(vis,0,sizeof(vis)); printf("Top sticks:"); firstt=0; for (i=1;i<=n;i++) { flag=0; for (j=i+1;j<=n;j++) { if (judge(a[i].s,a[i].t,a[j].s,a[j].t)) { flag=1; break; } } if (!flag) { if (!firstt) firstt=1; else printf(","); printf(" %d",i); } } puts("."); } }
POJ - 1066
中点通过,与通过线的任何方式无差异,问题还是转化为起点到终点通过几条线。
#include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<ctime> #include<cctype> #include<iostream> #include<algorithm> //#include<chrono> #include<vector> #include<list> #include<queue> #include<string> #include<set> #include<map> #define debug frelimiten("r.txt","r",stdin) #define mp make_pair #define ri register int using namespace std; typedef long long ll; typedef double lf; typedef pair<int, int> pii; const int maxn = 1050+10; const int INF = 0x3f3f3f3f; const int mod = 998244353; const double eps=1e-8; const double PI=acos(-1.0); inline ll read(){ll s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s*w;} ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;} int sgn(double x) { if(fabs(x)<eps) return 0; if(x<0) return -1; else return 1; } struct vec{ lf x,y; vec(lf x=0,lf y=0):x(x),y(y){} vec operator-(const vec &b){return vec(x-b.x,y-b.y);} vec operator+(const vec &b){return vec(x+b.x,y+b.y);} vec operator*(lf k){return vec(k*x,k*y);} lf operator ^(const vec &b){return x*b.y-y-b.x;} lf len(){return hypot(x,y);} lf sqr(){return x*x+y*y;} /*截取*/vec trunc(lf k=1){return *this*(k/len());} /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);} }q[maxn],pp; lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;}; lf cross(vec a,vec b,vec c){return cross(a-b,b-c);} lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;} bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);} bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);} /*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';} bool judge(vec a,vec b,vec c,vec d){ //线段ab和线段cd #define SJ(x) max(a.x,b.x)<min(c.x,d.x) || max(c.x,d.x)<min(a.x,b.x) if(SJ(x) || SJ(y))return 0; #define SJ2(a,b,c,d) cross(a-b,a-c)*cross(a-b,a-d)<=0 return SJ2(a,b,c,d) && SJ2(c,d,a,b); } int n,i,minn,j,num; double targetx,targety,x1,y1,x2,y2; int main() { n=read(); for (i=1;i<=2*n;i+=2) { scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); q[i]=vec(x1,y1); q[i+1]=vec(x2,y2); } scanf("%lf%lf",&targetx,&targety); pp=vec(targetx,targety); minn=INF; for (i=1;i<=2*n;i++) { num=0; for (j=1;j<=2*n;j+=2) { if (judge(q[i],pp,q[j],q[j+1])) num++; } minn=min(minn,num); } if (!n) printf("Number of doors = 1"); else printf("Number of doors = %d",minn); return 0; }
POJ - 1410
在矩阵里面也算相交
#include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<ctime> #include<cctype> #include<iostream> #include<algorithm> //#include<chrono> #include<vector> #include<list> #include<queue> #include<string> #include<set> #include<map> #define debug frelimiten("r.txt","r",stdin) #define mp make_pair #define ri register int using namespace std; typedef long long ll; typedef double lf; typedef pair<int, int> pii; const int maxn = 1050+10; const int INF = 0x3f3f3f3f; const int mod = 998244353; const double eps=1e-8; const double PI=acos(-1.0); inline ll read(){ll s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s*w;} ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;} int sgn(double x) { if(fabs(x)<eps) return 0; if(x<0) return -1; else return 1; } struct vec{ lf x,y; vec(lf x=0,lf y=0):x(x),y(y){} vec operator-(const vec &b){return vec(x-b.x,y-b.y);} vec operator+(const vec &b){return vec(x+b.x,y+b.y);} vec operator*(lf k){return vec(k*x,k*y);} lf operator ^(const vec &b){return x*b.y-y-b.x;} lf len(){return hypot(x,y);} lf sqr(){return x*x+y*y;} /*截取*/vec trunc(lf k=1){return *this*(k/len());} /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);} }q[maxn],pp; lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;}; lf cross(vec a,vec b,vec c){return cross(a-b,b-c);} lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;} bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);} bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);} /*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';} bool judge(vec a,vec b,vec c,vec d){ //线段ab和线段cd #define SJ(x) max(a.x,b.x)<min(c.x,d.x) || max(c.x,d.x)<min(a.x,b.x) if(SJ(x) || SJ(y))return 0; #define SJ2(a,b,c,d) cross(a-b,a-c)*cross(a-b,a-d)<=0 return SJ2(a,b,c,d) && SJ2(c,d,a,b); } struct Line { vec s,t; }line,rectangle[5]; bool flag; int n; double x,y,xx,yy; int main() { n=read(); while (n--) { scanf("%lf%lf",&x,&y); line.s=vec(x,y); scanf("%lf%lf",&x,&y); line.t=vec(x,y); scanf("%lf%lf",&x,&y); scanf("%lf%lf",&xx,&yy); if (x>xx) swap(x,xx); if (y<yy) swap(y,yy); rectangle[1].s=vec(x,y),rectangle[1].t=vec(x,yy); rectangle[2].s=vec(x,y),rectangle[2].t=vec(xx,y); rectangle[3].s=vec(xx,yy),rectangle[3].t=vec(xx,y); rectangle[4].s=vec(xx,yy),rectangle[4].t=vec(x,yy); flag=0; for (int i=1;i<=4;i++) { if (judge(line.s,line.t,rectangle[i].s,rectangle[i].t)) { flag=1; break; } } if (x<=line.s.x && line.s.x<=xx && yy<=line.s.y && line.s.y<=y) flag=1; if (x<=line.t.x && line.t.x<=xx && yy<=line.t.y && line.t.y<=y) flag=1; if (flag) printf("T "); else printf("F "); } return 0; }
POJ - 1696
极角排序
#include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<ctime> #include<cctype> #include<iostream> #include<algorithm> //#include<chrono> #include<vector> #include<list> #include<queue> #include<string> #include<set> #include<map> #define debug frelimiten("r.txt","r",stdin) #define mp make_pair #define ri register int using namespace std; typedef long long ll; typedef double lf; typedef pair<int, int> pii; const int maxn = 1050+10; const int INF = 0x3f3f3f3f; const int mod = 998244353; const double eps=1e-8; const double PI=acos(-1.0); inline ll read(){ll s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s*w;} ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;} int sgn(double x) { if(fabs(x)<eps) return 0; if(x<0) return -1; else return 1; } struct vec{ lf x,y; int num; vec(lf x=0,lf y=0):x(x),y(y){} vec operator-(const vec &b){return vec(x-b.x,y-b.y);} vec operator+(const vec &b){return vec(x+b.x,y+b.y);} vec operator*(lf k){return vec(k*x,k*y);} lf operator ^(const vec &b){return x*b.y-y-b.x;} lf len(){return hypot(x,y);} lf sqr(){return x*x+y*y;} /*截取*/vec trunc(lf k=1){return *this*(k/len());} /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);} }p[maxn]; lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;}; lf cross(vec a,vec b,vec c){return cross(a-b,b-c);} lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;} bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);} bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);} /*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';} int t,n,i,ans[maxn]; bool cmp(vec p1,vec p2) { double temp; temp=cross(p1,p2,p[i-1]); if (sgn(temp)>0) return true; else if (sgn(temp)==0 && ((p1-p[i-1]).len())<((p2-p[i-1]).len())) return true; return false; } int main() { t=read(); while (t--) { n=read(); for (i=0;i<n;i++) { p[i].num=read(); cin>>p[i].x>>p[i].y; if (p[i].y<p[0].y) swap(p[0],p[i]); } // sort(p+1,p+n,cmp); ans[0]=p[0].num; for (i=1;i<n;i++) { sort(p+i,p+n,cmp); ans[i]=p[i].num; } cout<<n; for (i=0;i<n;i++) printf(" %d",ans[i]); cout<<endl; } return 0; }
POJ - 3347
这题看了别人的思路感觉十分的巧妙,首先我们把所以线增大√2倍,然后再通过对前者矩阵的比较,算出左端点和右端点,这时就可以一个个判断是否有遮挡即可。
#include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<ctime> #include<cctype> #include<iostream> #include<algorithm> //#include<chrono> #include<vector> #include<list> #include<queue> #include<string> #include<set> #include<map> #define debug frelimiten("r.txt","r",stdin) #define mp make_pair #define ri register int using namespace std; typedef long long ll; typedef double lf; typedef pair<int, int> pii; const int maxn = 1050+10; const int INF = 0x3f3f3f3f; const int mod = 998244353; const double eps=1e-8; const double PI=acos(-1.0); inline ll read(){ll s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s*w;} ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;} int sgn(double x) { if(fabs(x)<eps) return 0; if(x<0) return -1; else return 1; } struct vec{ lf x,y; int num; vec(lf x=0,lf y=0):x(x),y(y){} vec operator-(const vec &b){return vec(x-b.x,y-b.y);} vec operator+(const vec &b){return vec(x+b.x,y+b.y);} vec operator*(lf k){return vec(k*x,k*y);} lf operator ^(const vec &b){return x*b.y-y-b.x;} lf len(){return hypot(x,y);} lf sqr(){return x*x+y*y;} /*截取*/vec trunc(lf k=1){return *this*(k/len());} /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);} }p[maxn]; lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;}; lf cross(vec a,vec b,vec c){return cross(a-b,b-c);} lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;} bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);} bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);} /*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';} struct node { int l,r,len; }; int n,i,j; int solve(node a,node b) { if (a.len<=b.len) return b.l+b.len+a.len; else return b.r+b.len-a.len; } int main() { node a[55]; while (~scanf("%d",&n),n) { for (i=0;i<n;i++) { scanf("%d",&a[i].len); a[i].l=0; for (j=0;j<i;j++) a[i].l=max(a[i].l,solve(a[i],a[j])); a[i].r=a[i].l+2*a[i].len; } for (i=1;i<n;i++) for (j=0;j<i;j++) { if (a[i].len<a[j].len && a[i].l<a[j].r) a[i].l=a[j].r; else if (a[i].len>a[j].len && a[i].l<a[j].r) a[j].r=a[i].l; } for (i=0;i<n;i++) if (a[i].l<a[i].r) printf("%d ",i+1); printf(" "); } return 0; }
POJ - 1039
首先如果存在能通过这个管道的线,那么我们对这条线稍微转一下角度,必会有先交到两个点,所以枚举两个端点,如果这条过这两个端点的直线能够通过整个管道,则得到答案。
若不能,我们每次取射到的最远距离即可。
#include<cstdio> #include<cmath> #include<cstring> #include<cstdlib> #include<ctime> #include<iomanip> #include<cctype> #include<iostream> #include<algorithm> //#include<chrono> #include<vector> #include<list> #include<queue> #include<string> #include<set> #include<map> #define debug frelimiten("r.txt","r",stdin) #define mp make_pair #define ri register int using namespace std; typedef long long ll; typedef double lf; typedef pair<int, int> pii; const int maxn = 1050+10; const int INF = 0x3f3f3f3f; const int mod = 998244353; const double eps=1e-8; const double PI=acos(-1.0); inline ll read(){ll s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s*w;} ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;} int sgn(double x) { if(fabs(x)<eps) return 0; if(x<0) return -1; else return 1; } struct vec{ lf x,y; int num; vec(lf x=0,lf y=0):x(x),y(y){} vec operator-(const vec &b){return vec(x-b.x,y-b.y);} vec operator+(const vec &b){return vec(x+b.x,y+b.y);} vec operator*(lf k){return vec(k*x,k*y);} lf operator ^(const vec &b){return x*b.y-y-b.x;} lf len(){return hypot(x,y);} lf sqr(){return x*x+y*y;} /*截取*/vec trunc(lf k=1){return *this*(k/len());} /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);} }down[maxn],up[maxn]; lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;}; lf cross(vec a,vec b,vec c){return cross(a-b,b-c);} lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;} bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);} bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);} /*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';} bool judge(vec a,vec b,vec c,vec d) { return (sgn(cross(a,b,c))*sgn(cross(a,b,d))<=0); } double solve(vec a,vec b,vec c,vec d) { lf area1=cross(a,b,c); lf area2=cross(a,b,d); int num1=sgn(area1); int num2=sgn(area2); if (num1*num2<0) return (area2*c.x-area1*d.x)/(area2-area1); if (num1*num2==0) { if (num1==0) return c.x; else return d.x; } return -INF; } double ans,maxx; int n,i,j,k; bool flag; int main() { while (~scanf("%d",&n)) { if (n==0) return 0; for (i=1;i<=n;i++) { scanf("%lf%lf",&up[i].x,&up[i].y); down[i].x=up[i].x; down[i].y=up[i].y-1; } maxx=-INF; flag=false; for (i=1;i<=n&&!flag;i++) for (j=1;j<=n&&!flag;j++) if (i!=j) { for (k=1;k<=n;k++) if (!judge(up[i],down[j],up[k],down[k])) break; if (k>n) { flag=true; } else if (k>max(i,j)) { ans=solve(up[i],down[j],up[k],up[k-1]); if (maxx<ans) maxx=ans; ans=solve(up[i],down[j],down[k],down[k-1]); if (maxx<ans) maxx=ans; } } if(flag) cout<<"Through all the pipe."<<endl; else cout<<fixed<<setprecision(2)<<maxx<<endl; } }