码迷,mamicode.com
首页 > 其他好文 > 详细

计算几何

时间:2016-05-10 23:22:25      阅读:250      评论:0      收藏:0      [点我收藏+]

标签:

 

POJ 2653 求最上面覆盖的线段

用一个set维护最上面的线段。删除,插入log(n)。删完set里的数后马上it++

主要是查看线段是否交。首先两个线段的矩形要相交。

然后判断一条线段的两个端点是否跨过另外一条线段所在的直线(用叉积乘积<0判断)

同理另外一条也要检查。

技术分享
 1 #include <cstring>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <cmath>
 6 #include <set>
 7 using namespace std;
 8 const int Inf=0x3f3f3f3f;
 9 const double eps=1e-8;
10 int n;
11 struct Vector
12 {
13     double x,y;
14     Vector(double x=0,double y=0):x(x),y(y){}
15 }P[100100],Q[100100];
16 inline double Min(double A,double B) {return A>B?B:A;}
17 inline double Max(double A,double B) {return A>B?A:B;}
18 inline Vector operator - (Vector A,Vector B) {return Vector(A.x-B.x,A.y-B.y);}
19 inline Vector operator + (Vector A,Vector B) {return Vector(A.x+B.x,A.y+B.y);}
20 inline Vector operator * (Vector A,double p) {return Vector(A.x*p,A.y*p);}
21 inline double Slope(Vector A) {if (fabs(A.x)<eps) return Inf; return A.y/A.x;}
22 inline double Cross(Vector A,Vector B) {return A.x*B.y-A.y*B.x;}
23 inline double Area2(Vector A,Vector B,Vector C) {return Cross(B-A,C-A);}
24 inline double Length(Vector A) {return sqrt(A.x*A.x+A.y*A.y);}
25 inline Vector GetLineInsersection(Vector P,Vector v,Vector Q,Vector w)
26 {
27     Vector u=P-Q;
28     double t=Cross(w,u)/Cross(v,w);
29     return P+v*t;
30 }
31 inline bool Check(Vector A,Vector B,Vector C,Vector D)
32 {
33     if (Max(A.x,B.x)<Min(C.x,D.x)) return false;
34     if (Min(A.x,B.x)>Max(C.x,D.x)) return false;
35     if (Max(A.y,B.y)<Min(C.y,D.y)) return false;
36     if (Min(A.y,B.y)>Max(C.y,D.y)) return false;
37     if (Area2(C,A,B)*Area2(D,A,B)>eps) return false;
38     if (Area2(A,C,D)*Area2(B,C,D)>eps) return false;
39     return true;
40 }
41 int main()
42 {
43     // freopen("c.in","r",stdin);
44     while (scanf("%d",&n)!=EOF)
45     {
46         if (n==0) break;
47         set<int> S;
48         for (int i=1;i<=n;i++)
49         {        
50             scanf("%lf%lf%lf%lf",&P[i].x,&P[i].y,&Q[i].x,&Q[i].y);
51             set<int>::iterator it;
52             for (it=S.begin();it!=S.end();)
53             {
54                 if (Check(P[*it],Q[*it],P[i],Q[i])) S.erase(it++);
55                 else it++;
56             }
57             S.insert(i);
58         }
59         printf("Top sticks:");
60         set<int>::iterator it=S.begin();
61         printf(" %d",*it++);
62         for (it;it!=S.end();it++) printf(", %d",*it);
63         puts(".");
64     }        
65     return 0;
66 }
C++

POJ 1556 求最短路径

同理判断叉积即可,最后用Floyd求最短路即可

技术分享
 1 #include <cstdio>
 2 #include <cmath>
 3 const double eps=1e-8;
 4 const int Inf=0x3f3f3f3f;
 5 struct Vector
 6 {
 7     double x,y;
 8     Vector(double x=0,double y=0):x(x),y(y){}
 9 }P[200];
10 int n;
11 double a1,a2,b1,b2,x,f[200][200];
12 inline Vector operator - (Vector A,Vector B) {return Vector(A.x-B.x,A.y-B.y);}
13 inline Vector operator + (Vector A,Vector B) {return Vector(A.x+B.x,A.y+B.y);}
14 inline Vector operator * (Vector A,double p) {return Vector(A.x*p,A.y*p);}
15 inline double Slope(Vector A) {if (fabs(A.x)<eps) return Inf; return A.y/A.x;}
16 inline double Cross(Vector A,Vector B) {return A.x*B.y-A.y*B.x;}
17 inline double Area2(Vector A,Vector B,Vector C) {return Cross(B-A,C-A);}
18 inline double Length(Vector A) {return sqrt(A.x*A.x+A.y*A.y);}
19 inline double Min(double A,double B) {return A>B?B:A;}
20 inline Vector GetLineInsersection(Vector P,Vector v,Vector Q,Vector w)
21 {
22     Vector u=P-Q;
23     double t=Cross(w,u)/Cross(v,w);
24     return P+v*t;
25 }
26 inline bool Check(int u,int v)
27 {
28     if (fabs(P[u].x-P[v].x)<eps) return false;
29     for (int i=u+1;i<=v-1;i++)
30     {
31         if (fabs(P[u].x-P[i].x)<eps || fabs(P[v].x-P[i].x)<eps) continue;
32         Vector T;
33         if (i%4==1)
34         {
35             T=Vector(P[i].x,0);
36             if (Area2(T,P[u],P[v])*Area2(P[i],P[u],P[v])<0) return false;
37         }
38         if (i%4==0)
39         {
40             T=Vector(P[i].x,10);
41             if (Area2(T,P[u],P[v])*Area2(P[i],P[u],P[v])<0) return false;
42         }
43         if (i%4==2)
44         {
45             T=Vector(P[i+1].x,P[i+1].y);
46             if (Area2(T,P[u],P[v])*Area2(P[i],P[u],P[v])<0) return false;
47         }
48     }
49     return true;
50 }
51 
52 int main()
53 {
54     // freopen("c.in","r",stdin);
55     while (scanf("%d",&n)!=EOF)
56     {
57         if (n==-1) break;
58         for (int i=0;i<n;i++)
59         {
60             scanf("%lf%lf%lf%lf%lf",&x,&a1,&b1,&a2,&b2);
61             P[i*4+1]=Vector(x,a1);
62             P[i*4+2]=Vector(x,b1);
63             P[i*4+3]=Vector(x,a2);
64             P[i*4+4]=Vector(x,b2);
65         }
66         P[0]=Vector(0,5);
67         P[n*4+1]=Vector(10,5);
68         for (int i=0;i<=4*n+1;i++)
69             for (int j=0;j<=4*n+1;j++) f[i][j]=Inf;
70         for (int i=0;i<=n*4+1;i++)
71             for (int j=i+1;j<=n*4+1;j++)
72                 if (Check(i,j))
73                     f[i][j]=f[j][i]=Length(P[i]-P[j]);
74                 
75         for (int k=0;k<=4*n+1;k++)
76             for (int i=0;i<=4*n+1;i++)
77                 for (int j=0;j<=4*n+1;j++)
78                     if (i!=j && j!=k)  f[i][j]=Min(f[i][j],f[i][k]+f[k][j]);
79         printf("%.2f\n",f[0][4*n+1]);
80     }
81     return 0;
82 }
C++

POJ 1269 判断直线是否平行,共线或求交点

平行和共线slope相等,共线时有向面积为0

求交点用向量求交

技术分享
 1 #include <cstdio>
 2 #include <cmath>
 3 const double eps=1e-8;
 4 const int Inf=0x3f3f3f3f;
 5 struct Vector
 6 {
 7     double x,y;
 8     Vector(double x=0,double y=0):x(x),y(y){}
 9 }P[2],Q[2];
10 int n;
11 double x,y;
12 inline Vector operator - (Vector A,Vector B) {return Vector(A.x-B.x,A.y-B.y);}
13 inline Vector operator + (Vector A,Vector B) {return Vector(A.x+B.x,A.y+B.y);}
14 inline Vector operator * (Vector A,double p) {return Vector(A.x*p,A.y*p);}
15 inline double Slope(Vector A) {if (fabs(A.x)<eps) return Inf; return A.y/A.x;}
16 inline double Cross(Vector A,Vector B) {return A.x*B.y-A.y*B.x;}
17 inline double Area2(Vector A,Vector B,Vector C) {return Cross(B-A,C-A);}
18 inline Vector GetLineInsersection(Vector P,Vector v,Vector Q,Vector w)
19 {
20     Vector u=P-Q;
21     double t=Cross(w,u)/Cross(v,w);
22     return P+v*t;
23 }
24 
25 int main()
26 {
27     //freopen("c.in","r",stdin);
28     scanf("%d",&n); int nn=n;
29     puts("INTERSECTING LINES OUTPUT");
30     for (int i=1;i<=nn;i++)
31     {
32         scanf("%lf%lf",&x,&y);
33         P[1]=Vector(x,y);
34         scanf("%lf%lf",&x,&y);
35         P[2]=Vector(x,y);
36         scanf("%lf%lf",&x,&y);
37         Q[1]=Vector(x,y);
38         scanf("%lf%lf",&x,&y);
39         Q[2]=Vector(x,y);
40         if (fabs(Slope(P[2]-P[1])-Slope(Q[2]-Q[1]))<eps)
41         {
42             if (fabs(Area2(P[2],P[1],Q[1]))<eps) 
43                 puts("LINE"); else puts("NONE");
44             continue;
45         }
46         Vector W=GetLineInsersection(P[1],P[2]-P[1],Q[1],Q[2]-Q[1]);
47         printf("POINT %.2f %.2f\n",W.x,W.y);
48     }
49     puts("END OF OUTPUT");
50     return 0;
51 }
C++

POJ 3304 判断是否有一条直线经过所有线段

就是枚举不同线段的两个端点。

技术分享
 1 #include <cstdio>
 2 #include <cmath>
 3 const double eps=1e-8;
 4 int KASE,n;
 5 bool flag;
 6 struct Vector
 7 {
 8     double x,y;
 9     Vector (double x=0,double y=0):x(x),y(y){}
10 }a[110],b[110];
11 inline Vector operator - (Vector A,Vector B) {return Vector(A.x-B.x,A.y-B.y);}
12 inline double Cross(Vector A,Vector B) {return A.x*B.y-A.y*B.x;}
13 inline double Area2(Vector A,Vector B,Vector C) {return Cross(B-A,C-A);}
14 inline bool Check(Vector A,Vector B)
15 {
16     if (fabs(A.x-B.x)<eps && fabs(A.y-B.y)<eps) return false;
17     for (int i=1;i<=n;i++)
18         if (Area2(a[i],A,B)*Area2(b[i],A,B)>eps) return false;
19     return true;
20 }
21 int main()
22 {
23     scanf("%d",&KASE);
24     for (int kase=1;kase<=KASE;kase++)
25     {
26         scanf("%d",&n);
27         for (int i=1;i<=n;i++)
28             scanf("%lf%lf%lf%lf",&a[i].x,&a[i].y,&b[i].x,&b[i].y);
29         flag=false;
30         if (n<3) flag=true;
31         for (int i=1;i<=n && !flag;i++)
32             for (int j=i+1;j<=n && !flag;j++)
33             {
34                 if (Check(a[i],a[j])) flag=true;
35                 if (Check(a[i],b[j])) flag=true;
36                 if (Check(b[i],a[j])) flag=true;
37                 if (Check(b[i],b[j])) flag=true;
38             }
39         if (flag) puts("Yes!"); else puts("No!");
40     }
41     return 0;
42 }
C++

POJ 2318/2398 就每个端点在的区域

一个点在它左边的线段的叉积和它右边线段的叉积的符号相反,二分答案即可

技术分享
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 using namespace std;
 5 const int Maxn=10000;
 6 int n,m,C[Maxn],x1,x2,y1,y2;
 7 int x,y,u,v;
 8 struct Vector
 9 {
10     int x,y;
11     Vector(int x=0,int y=0):x(x),y(y){}
12 }V[Maxn][2],P;
13 inline Vector operator - (Vector A,Vector B) {return Vector(A.x-B.x,A.y-B.y);}
14 inline int Cross(Vector A,Vector B) {return A.x*B.y-A.y*B.x;}
15 inline int Area2(Vector A,Vector B,Vector C) {return Cross(B-A,C-A);}
16 inline int Find(Vector P)
17 {
18     int l=0,r=n,ans;
19     // for (int i=0;i<n;i++)
20         // if (Area2(P,V[i+1][0],V[i+1][1])>0 && Area2(P,V[i][0],V[i+1][1])<0) return i;
21     while (true)
22     {
23         int mid=(l+r)>>1;
24         if (Area2(P,V[mid][0],V[mid][1])>0) r=mid; 
25         else l=mid;
26         if (l+1==r) break;
27     }
28     return l;
29     cout << P.x << " " << P.y << endl;;
30     for (int i=0;i<=n;i++) 
31         cout << Area2(P,V[i][1],V[i][0]) << " ";
32     cout << endl;
33     return 0;
34     // for (int i=l;i<=r;i++)
35          // if (Area2(P,V[i+1][0],V[i+1][1])>0 && Area2(P,V[i][0],V[i][1])<0) return i;
36 }
37 int main()
38 {
39     // freopen("c.in","r",stdin);
40     // freopen(")
41     while (scanf("%d%d%d%d%d%d",&n,&m,&x1,&y1,&x2,&y2)!=EOF)
42     {
43         if (n==0) break;
44         for (int i=1;i<=n;i++)
45         {
46             scanf("%d%d",&u,&v);
47             V[i][0]=Vector(v,y2); V[i][1]=Vector(u,y1);
48         }
49         V[0][0]=Vector(x1,y2); V[0][1]=Vector(x1,y1);
50         V[++n][0]=Vector(x2,y2); V[n][1]=Vector(x2,y1);
51         memset(C,0,sizeof(C));
52         for (int i=1;i<=m;i++)
53         {
54             scanf("%d%d",&x,&y);
55             P=Vector(x,y);
56             C[Find(P)]++;
57         }
58         for(int i=0;i<n;i++)
59             printf("%d: %d\n",i,C[i]);
60         printf("\n");
61     }
62     return 0;
63 }
C++

 

计算几何

标签:

原文地址:http://www.cnblogs.com/yyjxx2010xyu/p/5479612.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!