Problem A (hdu 1086)
You can Solve a Geometry Problem too
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 5559 Accepted Submission(s): 2660
Give you N (1<=N<=100) segments(线段), please output the number of all intersections(交点). You should count repeatedly if M (M>2) segments intersect at the same point.
Note:
You can assume that two segments would not intersect at more than one point.
A test case starting with 0 terminates the input and this test case is not to be processed.
题目大意:给你n个线段,让你求这些线段有多少个交点。
分析:线段相交的判断,使用快速排斥试验和跨立试验,快速排斥实验即计算两个线段为对角线的两个矩形是否有重合部分,跨立实验则是分别检测一个线段的两个点是不是在另一个线段的两侧(叉积符号相反)。
1 //============================================================================ 2 // Name : 基本函数模板.cpp 3 // Author : 4 // Version : 5 // Copyright : Your copyright notice 6 // Description : Hello World in C++, Ansi-style 7 //============================================================================ 8 #include <iostream> 9 #include <stdio.h> 10 #include <string.h> 11 #include <algorithm> 12 #include <queue> 13 #include <map> 14 #include <vector> 15 #include <set> 16 #include <string> 17 #include <math.h> 18 #define maxlen 110 19 using namespace std; 20 21 const double eps = 1e-8; 22 const double PI = acos(-1.0); 23 int sgn(double x) 24 { 25 if(fabs(x) < eps)return 0; 26 if(x < 0)return -1; 27 else return 1; 28 } 29 struct Point 30 { 31 double x,y; 32 Point(){} 33 Point(double _x,double _y) 34 { 35 x = _x;y = _y; 36 } 37 Point operator -(const Point &b)const 38 { 39 return Point(x - b.x,y - b.y); 40 } 41 //叉积 42 double operator ^(const Point &b)const 43 { 44 return x*b.y - y*b.x; 45 } 46 //点积 47 double operator *(const Point &b)const 48 { 49 return x*b.x + y*b.y; 50 } 51 //绕原点旋转角度B(弧度值),后x,y的变化 52 void transXY(double B) 53 { 54 double tx = x,ty = y; 55 x = tx*cos(B) - ty*sin(B); 56 y = tx*sin(B) + ty*cos(B); 57 } 58 }; 59 struct Line 60 { 61 Point s,e; 62 Line(){} 63 Line(Point _s,Point _e) 64 { 65 s = _s;e = _e; 66 } 67 //两直线相交求交点 68 //第一个值为0表示直线重合,为1表示平行,为0表示相交,为2是相交 69 //只有第一个值为2时,交点才有意义 70 pair<int,Point> operator &(const Line &b)const 71 { 72 Point res = s; 73 if(sgn((s-e)^(b.s-b.e)) == 0) 74 { 75 if(sgn((s-b.e)^(b.s-b.e)) == 0) 76 return make_pair(0,res);//重合 77 else return make_pair(1,res);//平行 78 } 79 double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e)); 80 res.x += (e.x-s.x)*t; 81 res.y += (e.y-s.y)*t; 82 return make_pair(2,res); 83 } 84 }; 85 //*两点间距离 86 double dist(Point a,Point b) 87 { 88 return sqrt((a-b)*(a-b)); 89 } 90 //*判断线段相交 91 bool inter(Line l1,Line l2) 92 { 93 return 94 max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) && 95 max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) && 96 max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) && 97 max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) && 98 sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e)) <= 0 && 99 sgn((l1.s-l2.e)^(l2.s-l2.e))*sgn((l1.e-l2.e)^(l2.s-l2.e)) <= 0; 100 } 101 //判断直线和线段相交 102 bool Seg_inter_line(Line l1,Line l2) //判断直线l1和线段l2是否相交 103 { 104 return sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e)) <= 0; 105 } 106 //点到直线距离 107 //返回为result,是点到直线最近的点 108 Point PointToLine(Point P,Line L) 109 { 110 Point result; 111 double t = ((P-L.s)*(L.e-L.s))/((L.e-L.s)*(L.e-L.s)); 112 result.x = L.s.x + (L.e.x-L.s.x)*t; 113 result.y = L.s.y + (L.e.y-L.s.y)*t; 114 return result; 115 } 116 //点到线段的距离 117 //返回点到线段最近的点 118 Point NearestPointToLineSeg(Point P,Line L) 119 { 120 Point result; 121 double t = ((P-L.s)*(L.e-L.s))/((L.e-L.s)*(L.e-L.s)); 122 if(t >= 0 && t <= 1) 123 { 124 result.x = L.s.x + (L.e.x - L.s.x)*t; 125 result.y = L.s.y + (L.e.y - L.s.y)*t; 126 } 127 else 128 { 129 if(dist(P,L.s) < dist(P,L.e)) 130 result = L.s; 131 else result = L.e; 132 } 133 return result; 134 } 135 //计算多边形面积 136 //点的编号从0~n-1 137 double CalcArea(Point p[],int n) 138 { 139 double res = 0; 140 for(int i = 0;i < n;i++) 141 res += (p[i]^p[(i+1)%n])/2; 142 return fabs(res); 143 } 144 //*判断点在线段上 145 bool OnSeg(Point P,Line L) 146 { 147 return 148 sgn((L.s-P)^(L.e-P)) == 0 && 149 sgn((P.x - L.s.x) * (P.x - L.e.x)) <= 0 && 150 sgn((P.y - L.s.y) * (P.y - L.e.y)) <= 0; 151 } 152 int n; 153 Line a[maxlen]; 154 int main() 155 { 156 while(scanf("%d",&n)!=EOF) 157 { 158 if(n==0) 159 break; 160 for(int i=0;i<n;++i) 161 { 162 scanf("%lf%lf%lf%lf",&a[i].s.x,&a[i].s.y,&a[i].e.x,&a[i].e.y); 163 } 164 int cnt=0; 165 for(int i=0;i<n;++i) 166 { 167 for(int j=i+1;j<n;++j) 168 { 169 if(inter(a[i],a[j])) 170 cnt++; 171 } 172 } 173 printf("%d ",cnt); 174 } 175 return 0; 176 }
Problem C(poj 1296)
Intersecting Lines
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 8450 | Accepted: 3840 |
Description
Your program will repeatedly read in four points that define two lines in the x-y plane and determine how and where the lines intersect. All numbers required by this problem will be reasonable, say between -1000 and 1000.
Input
Output
Sample Input
5 0 0 4 4 0 4 4 0 5 0 7 6 1 0 2 3 5 0 7 6 3 -6 4 -3 2 0 2 27 1 5 18 5 0 3 4 0 1 2 2 5
Sample Output
INTERSECTING LINES OUTPUT POINT 2.00 2.00 NONE LINE POINT 2.00 5.00 POINT 1.07 2.20 END OF OUTPUT
Source
题目大意:判断两个线段的关系,(相交、平行、重合)如果相交,求出交点。1 #include <iostream> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 struct point 6 { 7 double x,y; 8 }; 9 point mid; 10 int Inter(point a,point b,point c,point d)//平行返回0 重合返回1 相交返回2 11 { 12 double A1=b.y-a.y,A2=d.y-c.y,B1=a.x-b.x,B2=c.x-d.x; 13 double C1=b.y*(b.x-a.x)-b.x*(b.y-a.y),C2=d.y*(d.x-c.x)-d.x*(d.y-c.y); 14 if(A1*B2==B1*A2) 15 { 16 if(A2*C1==A1*C2&&B1*C2==B2*C1) 17 return 1; 18 return 0; 19 } 20 mid.x=(B1*C2-B2*C1)/(B2*A1-B1*A2); 21 mid.y=(A1*C2-A2*C1)/(A2*B1-A1*B2); 22 return 2; 23 } 24 int main() 25 { 26 point a,b,c,d; 27 int n; 28 while(scanf("%d",&n)!=EOF) 29 { 30 puts("INTERSECTING LINES OUTPUT"); 31 while(n--) 32 { 33 scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y,&c.x,&c.y,&d.x,&d.y); 34 int ans=Inter(a,b,c,d); 35 if(ans==0) 36 printf("NONE "); 37 else if(ans==1) 38 printf("LINE "); 39 else 40 printf("POINT %.2f %.2f ",mid.x,mid.y); 41 } 42 puts("END OF OUTPUT"); 43 } 44 return 0; 45 }
Problem D (poj 2653)
Pick-up sticks
Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 7807 | Accepted: 2881 |
Description
Input
Output
The picture to the right below illustrates the first case from input.
Sample Input
5 1 1 4 2 2 3 3 1 1 -2.0 8 4 1 4 8 2 3 3 6 -2.0 3 0 0 1 1 1 0 2 1 2 0 3 1 0
Sample Output
Top sticks: 2, 4, 5. Top sticks: 1, 2, 3.
Hint
Source
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <algorithm> 5 #include <queue> 6 #include <map> 7 #include <vector> 8 #include <set> 9 #include <string> 10 #include <math.h> 11 using namespace std; 12 13 const double eps = 1e-8; 14 const double PI = acos(-1.0); 15 int sgn(double x) 16 { 17 if(fabs(x) < eps)return 0; 18 if(x < 0)return -1; 19 else return 1; 20 } 21 struct Point 22 { 23 double x,y; 24 Point(){} 25 Point(double _x,double _y) 26 { 27 x = _x;y = _y; 28 } 29 Point operator -(const Point &b)const 30 { 31 return Point(x - b.x,y - b.y); 32 } 33 //叉积 34 double operator ^(const Point &b)const 35 { 36 return x*b.y - y*b.x; 37 } 38 //点积 39 double operator *(const Point &b)const 40 { 41 return x*b.x + y*b.y; 42 } 43 //绕原点旋转角度B(弧度值),后x,y的变化 44 void transXY(double B) 45 { 46 double tx = x,ty = y; 47 x = tx*cos(B) - ty*sin(B); 48 y = tx*sin(B) + ty*cos(B); 49 } 50 }; 51 struct Line 52 { 53 Point s,e; 54 Line(){} 55 Line(Point _s,Point _e) 56 { 57 s = _s;e = _e; 58 } 59 }; 60 //*两点间距离 61 double dist(Point a,Point b) 62 { 63 return sqrt((a-b)*(a-b)); 64 } 65 //*判断线段相交 66 bool inter(Line l1,Line l2) 67 { 68 return 69 max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) && 70 max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) && 71 max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) && 72 max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) && 73 sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e)) <= 0 && 74 sgn((l1.s-l2.e)^(l2.s-l2.e))*sgn((l1.e-l2.e)^(l2.s-l2.e)) <= 0; 75 } 76 const int MAXN = 100010; 77 Line l[MAXN]; 78 bool f[MAXN]; 79 int n; 80 int main () 81 { 82 while(scanf("%d",&n)!=EOF) 83 { 84 if(n==0) 85 break; 86 for(int i=0;i<n;++i) 87 { 88 scanf("%lf%lf%lf%lf",&l[i].s.x,&l[i].s.y,&l[i].e.x,&l[i].e.y); 89 } 90 memset(f,0,sizeof(f)); 91 for(int i=0;i<n;++i) 92 { 93 for(int j=i+1;j<n;++j) 94 { 95 if(inter(l[i],l[j])) 96 { 97 f[i]=1; 98 break; 99 } 100 } 101 } 102 printf("Top sticks:"); 103 for(int i=0;i<n;++i) 104 { 105 if(f[i]==0) 106 { 107 if(i!=n-1) 108 printf(" %d,",i+1); 109 else 110 printf(" %d. ",i+1); 111 } 112 } 113 } 114 115 }
Problem G (poj 2954)
Triangle
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 4394 | Accepted: 1942 |
Description
A lattice point is an ordered pair (x, y) where x and y are both integers. Given the coordinates of the vertices of a triangle (which happen to be lattice points), you are to count the number of lattice points which lie completely inside of the triangle (points on the edges or vertices of the triangle do not count).
Input
The input test file will contain multiple test cases. Each input test case consists of six integers x1, y1, x2, y2, x3, and y3, where (x1, y1), (x2, y2), and (x3, y3) are the coordinates of vertices of the triangle. All triangles in the input will be non-degenerate (will have positive area), and −15000 ≤ x1, y1, x2, y2, x3, y3 ≤ 15000. The end-of-file is marked by a test case with x1 = y1 = x2 = y2 = x3 = y3 = 0 and should not be processed.
Output
For each input case, the program should print the number of internal lattice points on a single line.
Sample Input
0 0 1 0 0 1 0 0 5 0 0 5 0 0 0 0 0 0
Sample Output
0 6
Source
线段上的格点数算法:包括端点的整点个数为gcd(abs(x1-x2),abs(y1-y2))+1个
Pick公式:整点多边形的面积=内部整点个数+边上的整点个数/2-1.
1 #include <iostream> 2 #include <cstdio> 3 #include <string.h> 4 #include <algorithm> 5 #include <queue> 6 #include <map> 7 #include <vector> 8 #include <set> 9 #include <string> 10 #include <math.h> 11 using namespace std; 12 13 const double eps = 1e-8; 14 const double PI = acos(-1.0); 15 int sgn(double x) 16 { 17 if(fabs(x) < eps)return 0; 18 if(x < 0)return -1; 19 else return 1; 20 } 21 struct Point 22 { 23 int x,y; 24 Point(){} 25 Point(int _x,int _y) 26 { 27 x = _x;y = _y; 28 } 29 Point operator -(const Point &b)const 30 { 31 return Point(x - b.x,y - b.y); 32 } 33 //叉积 34 double operator ^(const Point &b)const 35 { 36 return x*b.y - y*b.x; 37 } 38 //点积 39 double operator *(const Point &b)const 40 { 41 return x*b.x + y*b.y; 42 } 43 //绕原点旋转角度B(弧度值),后x,y的变化 44 void transXY(double B) 45 { 46 double tx = x,ty = y; 47 x = tx*cos(B) - ty*sin(B); 48 y = tx*sin(B) + ty*cos(B); 49 } 50 }; 51 int gcd(int a,int b) 52 { 53 if(b==0) 54 return a; 55 return gcd(b,a%b); 56 } 57 int myabs(int a) 58 { 59 return a<0?-a:a; 60 } 61 int main() 62 { 63 Point a,b,c; 64 while(scanf("%d%d%d%d%d%d",&a.x,&a.y,&b.x,&b.y,&c.x,&c.y)!=EOF) 65 { 66 if(a.x==0&&a.y==0&&b.x==0&&b.y==0&&c.x==0&&c.y==0) 67 break; 68 int s=myabs((b-a)^(c-a)); 69 int e=gcd(abs(a.x-b.x),abs(a.y-b.y))+gcd(abs(a.x-c.x),abs(a.y-c.y))+gcd(abs(c.x-b.x),abs(c.y-b.y)); 70 int ans=(s-e+2)/2; 71 printf("%d ",ans); 72 } 73 }
Problem H (poj 2954)
Shape of HDU
Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4276 Accepted Submission(s): 1899
创业是需要地盘的,HDU向钱江肉丝高新技术开发区申请一块用地,很快得到了批复,据说这是因为他们公司研发的“海东牌”老鼠药科技含量很高,预期将占全球一半以上的市场。政府划拨的这块用地是一个多边形,为了描述它,我们用逆时针方向的顶点序列来表示,我们很想了解这块地的基本情况,现在请你编程判断HDU的用地是凸多边形还是凹多边形呢?
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <algorithm> 5 #include <queue> 6 #include <map> 7 #include <vector> 8 #include <set> 9 #include <string> 10 #include <math.h> 11 #define maxlen 1010 12 using namespace std; 13 14 const double eps = 1e-8; 15 const double PI = acos(-1.0); 16 int sgn(double x) 17 { 18 if(fabs(x) < eps)return 0; 19 if(x < 0)return -1; 20 else return 1; 21 } 22 struct Point 23 { 24 double x,y; 25 Point() {} 26 Point(double _x,double _y) 27 { 28 x = _x; 29 y = _y; 30 } 31 Point operator -(const Point &b)const 32 { 33 return Point(x - b.x,y - b.y); 34 } 35 //叉积 36 double operator ^(const Point &b)const 37 { 38 return x*b.y - y*b.x; 39 } 40 //点积 41 double operator *(const Point &b)const 42 { 43 return x*b.x + y*b.y; 44 } 45 //绕原点旋转角度B(弧度值),后x,y的变化 46 void transXY(double B) 47 { 48 double tx = x,ty = y; 49 x = tx*cos(B) - ty*sin(B); 50 y = tx*sin(B) + ty*cos(B); 51 } 52 }; 53 bool isconvex(Point poly[],int n) 54 { 55 //bool s[3]; 56 //memset(s,false,sizeof(s)); 57 for(int i = 0; i < n; i++) 58 { 59 double temp=(poly[(i+1)%n].x-poly[i].x)*(poly[(i+2)%n].y-poly[i].y) - (poly[(i+2)%n].x-poly[i].x)*(poly[(i+1)%n].y-poly[i].y); 60 if(temp<0) 61 { 62 return false; 63 } 64 } 65 return true; 66 } 67 Point p[maxlen]; 68 int n; 69 int main() 70 { 71 while(scanf("%d",&n)!=EOF) 72 { 73 if(n==0) 74 break; 75 for(int i=0; i<n; ++i) 76 scanf("%d%d",&p[i].x,&p[i].y); 77 if(isconvex(p,n)) 78 printf("convex "); 79 else 80 printf("concave "); 81 } 82 return 0; 83 }
Problem H (hdu 1392)
Surround the Trees
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 5995 Accepted Submission(s): 2256
The diameter and length of the trees are omitted, which means a tree can be seen as a point. The thickness of the rope is also omitted which means a rope can be seen as a line.
Zero at line for number of trees terminates the input for your program.
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <algorithm> 5 #include <math.h> 6 #include <iomanip> 7 using namespace std; 8 9 const double eps = 1e-8; 10 const double PI = acos(-1.0); 11 int sgn(int x) 12 { 13 if(fabs(double (x)) < eps)return 0; 14 if(x < 0)return -1; 15 else return 1; 16 } 17 struct Point 18 { 19 int x,y; 20 Point() {} 21 Point(int _x,int _y) 22 { 23 x = _x; 24 y = _y; 25 } 26 Point operator -(const Point &b)const 27 { 28 return Point(x-b.x,y-b.y); 29 } 30 double operator ^(const Point &b)const 31 { 32 return x*b.y - y*b.x; 33 } 34 double operator *(const Point &b)const 35 { 36 return x*b.x + y*b.y; 37 } 38 }; 39 //*两点间距离 40 double dist(Point a,Point b) 41 { 42 return sqrt((a-b)*(a-b)); 43 } 44 45 const int MAXN = 1010; 46 Point list[MAXN]; 47 int Stack[MAXN],top; 48 //相对于list[0]的极角排序 49 bool cmp(Point p1,Point p2) 50 { 51 double tmp = (p1-list[0])^(p2-list[0]); 52 if(sgn(tmp) > 0)return true; 53 else if(sgn(tmp) == 0 && sgn(dist(p1,list[0]) - dist(p2,list[0])) <= 0) 54 return true; 55 else return false; 56 } 57 void Graham(int n) 58 { 59 Point p0; 60 int k = 0; 61 p0 = list[0]; 62 //找最下边的一个点 63 for(int i = 1; i < n; i++) 64 { 65 if( (p0.y > list[i].y) || (p0.y == list[i].y && p0.x > list[i].x) ) 66 { 67 p0 = list[i]; 68 k = i; 69 } 70 } 71 swap(list[k],list[0]); 72 sort(list+1,list+n,cmp); 73 if(n == 1) 74 { 75 top = 1; 76 Stack[0] = 0; 77 return; 78 } 79 if(n == 2) 80 { 81 top = 2; 82 Stack[0] = 0; 83 Stack[1] = 1; 84 return ; 85 } 86 Stack[0] = 0; 87 Stack[1] = 1; 88 top = 2; 89 for(int i = 2; i < n; i++) 90 { 91 while(top > 1 && sgn((list[Stack[top-1]]-list[Stack[top-2]])^(list[i]-list[Stack[top-2]])) <= 0) 92 top--; 93 Stack[top++] = i; 94 } 95 } 96 int n; 97 int main() 98 { 99 while(scanf("%d",&n)!=EOF) 100 { 101 if(n==0) 102 break; 103 for(int i=0; i<n; ++i) 104 scanf("%d%d",&list[i].x,&list[i].y); 105 Graham(n); 106 double ans=0.0; 107 if (top==2) 108 ans+=dist(list[0],list[1]); 109 else 110 { 111 for(int i=0; i<top; ++i) 112 { 113 ans+=dist(list[Stack[i]],list[Stack[(i+1)%top]]); 114 } 115 } 116 printf("%.2f ",ans); 117 } 118 return 0; 119 }
感谢kuangbin学长的模板,还是很好用的,不会的等填坑。╮(╯▽╰)╭