计算几何 (⊙o⊙)…
POJ 2318 TOYS(推荐)
http://acm.pku.edu.cn/JudgeOnline/problem?id=2318
#include<iostream> #include<cstring> #define y1 xy using namespace std; struct Point{ int x,y; Point() {} Point(int _x,int _y){ x=_x; y=_y; } Point operator +(const Point X)const{ return Point(x+X.x,y+X.y); } Point operator -(const Point X)const{ return Point(x-X.x,y-X.y); } }P; int Dit(Point X,Point Y){ return X.x*Y.x+X.y*Y.y; } int Det(Point X,Point Y){ return X.x*Y.y-X.y*Y.x; } struct Line{ Point S,T; Line() {} Line(Point _s,Point _t){ S=_s; T=_t; } }L[5007]; int ans[5007]; int Li_P(Point A,Line B){ return Det(B.S-A,B.T-A); } int n,m,x1,y1,x2,y2,x,y; int main () { // freopen("a.in","r",stdin); while (scanf("%d%d%d%d%d%d",&n,&m,&x1,&y1,&x2,&y2)!=EOF&&n) { for (int i=1;i<=n;i++) { scanf("%d%d",&x,&y); L[i]=Line(Point(x,y1),Point(y,y2)); } L[n+1]=Line(Point(x2,y1),Point(x2,y2)); for (int i=1;i<=m;i++) { scanf("%d%d",&P.x,&P.y); for (int i=1;i<=n+1;i++) if (Li_P(P,L[i])<0) { ans[i-1]++; break;} } for (int i=0;i<=n;i++) printf("%d: %d\n",i,ans[i]); memset(ans,0,sizeof ans); puts(""); } return 0; }
POJ 2398 Toy Storage(推荐)
http://acm.pku.edu.cn/JudgeOnline/problem?id=2398
一个矩形,有被若干直线分成N个格子,给出一个点的坐标,问你该点位于哪个点中。
知识点:其实就是点在凸四边形内的判断,若利用叉积的性质,可以二分求解。
#include<iostream> #include<cstring> #include<algorithm> #define y1 xy using namespace std; struct Point{ int x,y; Point() {} Point(int _x,int _y){ x=_x; y=_y; } Point operator +(const Point X)const{ return Point(x+X.x,y+X.y); } Point operator -(const Point X)const{ return Point(x-X.x,y-X.y); } }P; int Dit(Point X,Point Y){ return X.x*Y.x+X.y*Y.y; } int Det(Point X,Point Y){ return X.x*Y.y-X.y*Y.x; } struct Line{ Point S,T; Line() {} Line(Point _s,Point _t){ S=_s; T=_t; } bool operator <(const Line PP)const{ return (min(S.x,T.x)==min(PP.S.x,PP.T.x))? (min(S.y,T.y)<min(PP.S.y,PP.T.y)):min(S.x,T.x)<min(PP.S.x,PP.T.x); } }L[5007]; int ans[5007],cnt[5007]; int Li_P(Point A,Line B){ return Det(B.S-A,B.T-A); } int n,m,x1,y1,x2,y2,x,y; int main () { while (scanf("%d%d%d%d%d%d",&n,&m,&x1,&y1,&x2,&y2)!=EOF&&n) { for (int i=1;i<=n;i++) { scanf("%d%d",&x,&y); L[i]=Line(Point(x,y1),Point(y,y2)); } L[n+1]=Line(Point(x2,y1),Point(x2,y2)); sort(L+1,L+n+2); for (int i=1;i<=m;i++) { scanf("%d%d",&P.x,&P.y); for (int i=1;i<=n+1;i++) if (Li_P(P,L[i])<0) { ans[i-1]++; break;} } for (int i=0;i<=n;i++) cnt[ans[i]]++; printf("Box\n"); for (int i=1;i<=m;i++) if (cnt[i]!=0) printf("%d: %d\n",i,cnt[i]); memset(ans,0,sizeof ans); memset(cnt,0,sizeof ans); } return 0; }
POJ 3304 Segments
http://acm.pku.edu.cn/JudgeOnline/problem?id=3304
知识点:线段与直线相交,注意枚举时重合点的处理
#include<iostream> #include<cstring> #include<algorithm> #include<cmath> #define db double #define N 4007 const db pi=acos((db)-1); #define exp 1e-8 int dcmp(db x,db y) { if (abs(x-y)<exp) return 0; return x<y?-1:1; } using namespace std; struct Point{ db x,y; Point() {} Point(db _x,db _y):x(_x),y(_y){} void Int() {scanf("%lf%lf",&x,&y);} Point operator +(const Point X)const{ return Point(x+X.x,y+X.y); } Point operator -(const Point X)const{ return Point(x-X.x,y-X.y); } Point operator *(const db X)const{ return Point(x*X,y*X); } Point operator -(const db X)const{ return Point(x/X,y/X); } bool operator <(const Point X)const{ return dcmp(x,X.x)==0?y<X.y:x<X.x; } bool operator ==(const Point X)const{ return dcmp(x,X.x)==0&&dcmp(y,X.y)==0; } }; db Dit(Point X,Point Y){return X.x*Y.x+X.y*Y.y;} db Det(Point X,Point Y){return X.x*Y.y-X.y*Y.x;} struct Line{ Point S,T; void up() { if (T<S) swap(S,T); } void Int() { S.Int(); T.Int(); up(); } Line() {} Line(Point _s,Point _t){ S=_s; T=_t; up(); } }L[N]; db Li_P(Line X,Point T){ //线段和点的方向 return Det(X.S-T,X.T-T); } bool Li_Li(Line X,Line Y){ //直线和线段不严格交 if (Li_P(X,Y.S)*Li_P(X,Y.T)>exp) return 0; return 1; } int T,n,ans; bool check(Line P){ if (P.S==P.T) return 0; for (int i=1;i<=n;i++) if (!Li_Li(P,L[i])) return 0; return 1; } signed main () { freopen("c.in","r",stdin); scanf("%d",&T); while (T--) { scanf("%d",&n); for (int i=1;i<=n;i++) L[i].Int(); if (n==1) {puts("Yes!"); continue;} ans=0; for (int i=1;i<=n&&!ans;i++) for (int j=i+1;j<=n&&!ans;j++){ ans|=check(Line(L[i].S,L[j].S)); ans|=check(Line(L[i].S,L[j].T)); ans|=check(Line(L[i].T,L[j].S)); ans|=check(Line(L[i].T,L[j].T)); // if (ans) cerr<<i<<j<<endl; } puts(ans?"Yes!":"No!"); } return 0; }
POJ 1269 Intersecting Lines
http://acm.pku.edu.cn/JudgeOnline/problem?id=1269
知识点:直线相交判断,求相交交点
#include<iostream> #include<cstring> #include<algorithm> #include<cmath> #define db double #define N 4007 const db pi=acos((db)-1); #define exp 1e-8 int dcmp(db x) { if (abs(x)<exp) return 0; return x<0?-1:1; } int dcmp(db x,db y) { if (abs(x-y)<exp) return 0; return x<y?-1:1; } using namespace std; struct Point{ db x,y; Point() {} Point(db _x,db _y):x(_x),y(_y){} void Int() {scanf("%lf%lf",&x,&y);} Point operator +(const Point X)const{ return Point(x+X.x,y+X.y); } Point operator -(const Point X)const{ return Point(x-X.x,y-X.y); } Point operator *(const db X)const{ return Point(x*X,y*X); } Point operator -(const db X)const{ return Point(x/X,y/X); } bool operator <(const Point X)const{ return dcmp(x,X.x)==0?y<X.y:x<X.x; } bool operator ==(const Point X)const{ return dcmp(x,X.x)==0&&dcmp(y,X.y)==0; } }; db Dit(Point X,Point Y){return X.x*Y.x+X.y*Y.y;} db Det(Point X,Point Y){return X.x*Y.y-X.y*Y.x;} struct Line{ Point S,T; void up() { if (T<S) swap(S,T); } void Int() { S.Int(); T.Int(); up(); } Line() {} Line(Point _s,Point _t){ S=_s; T=_t; up(); } bool operator ==(const Line X)const{ return S==X.S&&T==X.T; } }X,Y; bool Pin(const Line Y,const Line X){ return dcmp(Det(Y.T-Y.S,X.T-X.S))==0; } db Li_P(Line X,Point T){ //线段和点的方向 return Det(X.S-T,X.T-T); } bool Li_Li(Line X,Line Y){ //直线和线段不严格交 if (Li_P(X,Y.S)*Li_P(X,Y.T)>exp) return 0; return 1; } bool ty(Line X,Line Y){ //尝试求交,判特殊情况 if (!Pin(X,Y)) return 0; if (dcmp(Li_P(X,Y.S))==0) { puts("LINE"); return 1;} puts("NONE"); return 1; } Point Jiao(Line X,Line Y){ //直线求交 Point res=X.S; db t=Det(X.S-Y.S,Y.S-Y.T)/Det(X.S-X.T,Y.S-Y.T); res.x+=(X.T.x-X.S.x)*t; res.y+=(X.T.y-X.S.y)*t; printf("POINT %.2lf %.2lf\n",res.x,res.y); return res; } int T,n,ans; signed main () { // freopen("d.in","r",stdin); scanf("%d",&T); puts("INTERSECTING LINES OUTPUT"); while (T--) { X.Int(); Y.Int(); if (ty(X,Y)) continue; Jiao(X,Y); } puts("END OF OUTPUT"); return 0; }
POJ 1410 Intersection
http://acm.pku.edu.cn/JudgeOnline/problem?id=1410
知识点:线段与矩形相交。正确理解题意中相交的定义。
#include<iostream> #include<cstring> #include<algorithm> #include<cmath> #define db double #define N 4007 const db pi=acos((db)-1); #define exp 1e-8 int dcmp(db x) { if (abs(x)<exp) return 0; return x<0?-1:1; } int dcmp(db x,db y) { if (abs(x-y)<exp) return 0; return x<y?-1:1; } using namespace std; struct Point{ db x,y; Point() {} Point(db _x,db _y):x(_x),y(_y){} void Int() {scanf("%lf%lf",&x,&y);} Point operator +(const Point X)const{ return Point(x+X.x,y+X.y); } Point operator -(const Point X)const{ return Point(x-X.x,y-X.y); } Point operator *(const db X)const{ return Point(x*X,y*X); } Point operator -(const db X)const{ return Point(x/X,y/X); } bool operator <(const Point X)const{ return dcmp(x,X.x)==0?y<X.y:x<X.x; } bool operator ==(const Point X)const{ return dcmp(x,X.x)==0&&dcmp(y,X.y)==0; } }; #define sqr(x) ((x)*(x)) db Dit(Point X,Point Y){return X.x*Y.x+X.y*Y.y;} db Det(Point X,Point Y){return X.x*Y.y-X.y*Y.x;} db Dis(Point X,Point Y){return sqrt(sqr(X.x-Y.x)+sqr(X.y-Y.y));} struct Line{ Point S,T,ET; void up() { if (T<S) swap(S,T); ET=T-S; } void Int() { S.Int(); T.Int(); up(); } Line() {} Line(Point _s,Point _t){ S=_s; T=_t; up(); } bool operator ==(const Line X)const{ return S==X.S&&T==X.T; } }X,Y; bool Pin(const Line Y,const Line X){ return dcmp(Det(Y.T-Y.S,X.T-X.S))==0; } db Li_P(Line X,Point T){ //线段和点的方向 return Det(X.S-T,X.T-T); } bool Li_Li(Line X,Line Y){ //直线和线段不严格交 if (Li_P(X,Y.S)*Li_P(X,Y.T)>exp) return 0; return 1; } bool Seg_Seg(Line X,Line Y){ //线段与线段不严格交 return Li_Li(X,Y)&&Li_Li(Y,X); } bool ty(Line X,Line Y){ //尝试求交,判特殊情况 if (!Pin(X,Y)) return 0; if (dcmp(Li_P(X,Y.S))==0) { /*puts("LINE");*/ return 1;} /*puts("NONE");*/ return 1; } Point Jiao(Line X,Line Y){ //直线求交 Point res=X.S; db t=Det(X.S-Y.S,Y.S-Y.T)/Det(X.S-X.T,Y.S-Y.T); res.x+=(X.T.x-X.S.x)*t; res.y+=(X.T.y-X.S.y)*t; // printf("POINT %.2lf %.2lf\n",res.x,res.y); return res; } int T,n,ans; bool che(Point X,Line S){ return dcmp(S.S.x,X.x)<=0&&dcmp(X.x,S.T.x)<=0&& dcmp(min(S.S.y,S.T.y),X.y)<=0&&dcmp(max(S.S.y,S.T.y),X.y)>=0; } //#define dblcmp dcmp //#define Max max //#define Min min //double Multi(Point p1, Point p2, Point p0) { // return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x); //} //bool SS(Line XX,Line YY) { // Point a=XX.S,b=XX.T,c=YY.S,d=YY.T; // if (dblcmp(Max(a.x, b.x)-Min(c.x, d.x)) >= 0 && dblcmp(Max(c.x, d.x)-Min(a.x, b.x)) >= 0 // && dblcmp(Max(a.y, b.y)-Min(c.y, d.y)) >= 0 && dblcmp(Max(c.y, d.y)-Min(a.y, b.y)) >= 0 // && dblcmp(Multi(a, d, c)*Multi(b, d, c)) <= 0 && dblcmp(Multi(c, b, a)*Multi(d, b, a)) <= 0) // return true; // return false; //} //#define Seg_Seg SS int main () { freopen("e.in","r",stdin); scanf("%d",&T); while (T--) { X.Int(); Y.Int(); ans=0; ans|=Seg_Seg(X,Line(Y.S,Point(Y.S.x,Y.T.y))); ans|=Seg_Seg(X,Line(Y.S,Point(Y.T.x,Y.S.y))); ans|=Seg_Seg(X,Line(Point(Y.S.x,Y.T.y),Y.T)); ans|=Seg_Seg(X,Line(Point(Y.T.x,Y.S.y),Y.T)); ans|=che(X.S,Y); ans|=che(X.T,Y); puts(ans?"T":"F"); } return 0; }
未完待续