计算几何基础与应用:HDU 1348&&ZOJ 1648&&POJ 2398&&ZOJ 1010

首先声明叉积在计算几何是基本用法!!他的奶名就叫做向量积!!(好熟悉的称呼)

那么叉积主要注意方向问题:他是以前面的向量为起点转向另外那个向量的角度!!

Wall  HDU 1348

一道模板题!!(凸包问题)

三步骤:排序,再排序,再是重点进行判断!!!

先进行排序,从小到大找出最左下角的一个坐标!

之后以这个坐标找出每个点的极角(用个三角公式atan2(y,x))

之后以三点为核心进行判断!!!

如果第三点在前两点连线的左边可以,不然回溯再进行判断!!

具体参见:http://hi.baidu.com/nicker2010/item/757c4350688a86a3adc857ed

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<algorithm>
 4 #include<math.h>
 5 #define PI 3.14159265
 6 using namespace std;
 7 struct line
 8 {
 9     double x;
10     double y;
11     double angle;
12 }a[1010],b[1010];
13 double comp(line i,line j)
14 {
15     if(i.y==j.y)
16         return i.x<j.x;
17     return i.y<j.y;
18 }
19 double comp1(line i,line j)
20 {
21     if(i.angle==j.angle)
22     {
23         if(i.x==j.x)
24             return i.y>j.y;
25         return i.x>j.x;
26     }
27     return i.angle<j.angle;
28 }
29 double add(line i,line j,line z)
30 {
31     double a1=z.y-i.y;
32     double a2=z.x-i.x;
33     double a3=z.y-j.y;
34     double a4=z.x-j.x;
35     return a2*a3-a1*a4;
36 }
37 double abb(line i,line j)
38 {
39     return sqrt((i.y-j.y)*(i.y-j.y)+(i.x-j.x)*(i.x-j.x));
40 }
41 int main()
42 {
43     int t,n,i,j,top;
44     double m,len;
45     scanf("%d",&t);
46     while(t--)
47     {
48         scanf("%d%lf",&n,&m);
49         for(i=1;i<=n;i++)
50             scanf("%lf%lf",&a[i].x,&a[i].y);
51         sort(a+1,a+n+1,comp);//排序
52         for(i=2;i<=n;i++)
53             a[i].angle=atan2(a[i].y-a[1].y,a[i].x-a[1].x);//求极角
54         sort(a+2,a+1+n,comp1);//再排序,第一个坐标不用排序
55         b[1]=a[1];//***********
56         b[2]=a[2];
57         b[3]=a[3];
58         top=4;
59         for(i=4;i<=n;i++)
60         {
61             while(top>3&&add(b[top-2],b[top-1],a[i])<=0)//以三点进行判断
62                 top--;
63             b[top++]=a[i];
64         }//**************核心
65         len=abb(b[1],b[top-1]);
66         for(i=2;i<top;i++)
67             len+=abb(b[i],b[i-1]);
68         len+=2*PI*m;
69         printf("%.0lf
",len);
70         if(t)
71             printf("
");
72     }
73     return 0;
74 }

Circuit Board ZOJ 1648

怎么用叉积判断两线段是否相交!!

有一种方法叫做:跨立实验

如果两线段相交,则两线段必然相互跨立对方。

P1P2跨立Q1Q2 ,则矢量 ( P1 - Q1 ) ( P2 - Q1 )位于矢量( Q2 - Q1 ) 的两侧,

( P1 - Q1 ) × ( Q2 - Q1 ) * ( P2 - Q1 ) × ( Q2 - Q1 ) < 0

那么就好做了:

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<stdio.h>
 4 #include<math.h>
 5 using namespace std;
 6 struct line
 7 {
 8     double x;
 9     double y;
10 }a[2005],b[2005];
11 double abb(double x1,double y1,double x2,double y2)
12 {
13     return x1*y2-y1*x2;
14 }
15 bool add(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4)
16 {
17     double temp1,temp2,temp3,temp4;
18     temp1=abb(x1-x3,y1-y3,x4-x3,y4-y3);
19     temp2=abb(x4-x3,y4-y3,x2-x3,y2-y3);
20     if(temp1*temp2>0)
21         return true;
22     return false;
23 }
24 int main()
25 {
26     int i,j,n,d;
27     while(scanf("%d",&n)!=EOF)
28     {
29         for(i=1;i<=n;i++)
30             scanf("%lf%lf%lf%lf",&a[i].x,&a[i].y,&b[i].x,&b[i].y);
31         d=0;
32         for(i=1;i<=n-1;i++)
33             {
34                 for(j=i+1;j<=n;j++)
35         {
36             if(add(a[i].x,a[i].y,b[i].x,b[i].y,a[j].x,a[j].y,b[j].x,b[j].y))
37             {
38                 d=1;
39                 break;
40             }
41         }
42         if(d==1)
43             break;
44             }
45         if(d==1)
46             printf("burned!
");
47         else
48             printf("ok!
");
49     }
50     return 0;
51 }//坐标表示可用结构体

 Toy Storage  POJ 2398

考点是:一个点是否在一个多边形内外!

但是这个题目的构造直接判断点在两条线段里面还是外面就可以了。。。

其实你都可以

把这个点做平行于x轴的射线,直接解方程得出x判断大小就可以了。。。

基本就是用叉积判断正负(也就是叉积的方向)。。。

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<algorithm>
 4 #include<string.h>
 5 using namespace std;
 6 int b[10005],n,y2,y1,x1,x2,x12,y12,m,i,c,x;
 7 struct line
 8 {
 9     int x1;
10     int x2;
11 }a[1005];
12 int comp1(line i,line j)
13 {
14     return i.x1<j.x1;
15 }
16 double abb(double x,double y,double x1,double y1)
17 {
18     return x*y1-x1*y;
19 }
20 int add(double x,int y,int i)
21 {
22     double d,d1;
23     d=abb(a[i].x1-x,y1-y,a[i].x2-x,y2-y);
24     if(i==1)
25     {
26         if(d<0)
27         {
28             b[i]++;
29             return 1;
30         }
31     }
32     else if(i==n+1)
33     {
34         if(d>0)
35         {
36             b[i]++;
37             return 1;
38         }
39     }
40     else
41     {
42         d1=abb(a[i-1].x1-x,y1-y,a[i-1].x2-x,y2-y);
43         if(d<0&&d1>0)
44         {
45             b[i]++;
46             return 1;
47         }
48     }
49     return 0;
50 }
51 int main()
52 {
53     while(scanf("%d",&n)!=EOF)
54     {
55         if(n==0)
56             break;
57         memset(b,0,sizeof(b));
58         scanf("%d%d%d%d%d",&m,&x1,&y1,&x2,&y2);
59         for(i=1;i<=n;i++)
60             scanf("%d%d",&a[i].x1,&a[i].x2);
61         sort(a+1,a+1+n,comp1);
62         a[n+1].x1=a[n].x1;a[n+1].x2=a[n].x2;
63         while(m--)
64         {
65             scanf("%d%d",&x12,&y12);
66             for(i=1;i<=n+1;i++)
67                 if(add(x12,y12,i))
68                     break;
69         }
70         sort(b+1,b+1+n+1);
71         int d=0;
72         c=1;x=0;
73         printf("Box
");
74         for(i=1;i<=n+1;i++)//*******输出形式搞了很久
75         {
76             if(b[i]!=0)
77             {
78                 c=b[i];
79                 while(b[i]==c&&i<=n+1)
80             {
81                 if(d==0)
82                 printf("%d: ",b[i]);
83                 d=1;
84                 i++;
85                 x++;
86             }
87             printf("%d
",x);
88             x=0;
89             d=0;
90             i--;
91             }
92         }//**************
93     }
94     return 0;
95 }

 Area  ZOJ 1010

一道简单的题目。。。

主要判断是不是多边形!!!

具体参见:http://blog.sina.com.cn/s/blog_5ced353d0100b1xd.html

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<stdio.h>
 4 using namespace std;
 5 double a[1005],b[1005];
 6 double abb(int i,int j,int k)
 7 {
 8     return (a[j]-a[i])*(b[j]-b[k])-(a[j]-a[k])*(b[j]-b[i]);
 9 }
10 int add(int x1,int y1,int x2,int y2)
11 {
12     if(abb(x2,x1,y1)*abb(y2,x1,y1)>0)//两次判断
13         return 0;
14     if(abb(x1,x2,y2)*abb(y1,x2,y2)>0)
15         return 0;
16   return 1;
17 }
18 int main()
19 {
20     int w=0,d,i,j,n;
21     double s;
22     while(scanf("%d",&n)!=EOF&&n)
23     {
24         if(w)
25             printf("
");
26         for(i=0;i<n;i++)
27             scanf("%lf%lf",&a[i],&b[i]);
28         if(n<3)
29         {
30             printf("Figure %d: Impossible
",++w);
31             continue;
32         }
33         d=0;
34         for(i=1;i<=n-1;i++)
35         {
36             for(j=1;j<=i-2;j++)
37                 if(add(i,i-1,j,j-1))//只需判断不相邻的边是否相交
38                     {d=1;break;}
39             if(d==1)
40                 break;
41         }
42         if(d==1)
43         {printf("Figure %d: Impossible
",++w);continue;}
44         for(i=2;i<n-1;i++)
45             if(add(0,n-1,i,i-1))
46                 {d=1;break;}
47         if(d==1)
48         {printf("Figure %d: Impossible
",++w);continue;}
49         s=0;
50         for(i=1;i<n;i++)
51             s+=a[i-1]*b[i]-a[i]*b[i-1];
52         s+=a[n-1]*b[0]-a[0]*b[n-1];
53         if(s<0)
54             s*=-1;
55         printf("Figure %d: %.2lf
",++w,s/2);
56     }
57     return 0;
58 }
原文地址:https://www.cnblogs.com/tt123/p/3273100.html