kuangbin专题十三-基础计算几何

链接:https://cn.vjudge.net/contest/68968

POJ 2318 TOYS

题意:m个玩具落在n+1个区间,给你玩具的坐标,问每个区间有多少玩具。

思路:叉积的简单应用,用叉积判断在直线的哪一侧,因为是顺序给出坐标,所以从左往右判断即可。

AC代码:

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn = 5e3 + 5;
 6 int U[maxn], L[maxn], ans[maxn];
 7 int Cross(int x1, int y1, int x2, int y2)
 8 {
 9     return x1 * y2 - x2 * y1;
10 }
11 int main()
12 {
13     int n, m, x1, y1, x2, y2;
14     int a, b;
15     while(~scanf("%d",&n) && n)
16     {
17         scanf("%d%d%d%d%d", &m, &x1, &y1, &x2, &y2);
18         for(int i = 0;i < n;i++)
19         {
20             scanf("%d %d",&U[i], &L[i]);
21         }
22         for(int i = 0;i <= n;i++) ans[i] = 0;
23         while(m--)
24         {
25             scanf("%d%d",&a, &b);
26             int i = 0;
27             for(i = 0;i < n;i++)
28             {
29                 if(Cross(a - L[i], b - y2, U[i] - L[i], y1 - y2) <= 0) break;
30             }
31             ans[i]++;
32         }
33         for(int i = 0;i <= n;i++) printf("%d: %d\n",i, ans[i]);
34         printf("\n");
35     }
36     return 0;
37 }
View Code

POJ 2398 Toy Storage

题意:同上一题类似,不过需要排序和改变输出。

AC代码:

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<algorithm>
 4 using namespace std;
 5 const int maxn = 5e3 + 5;
 6 int U[maxn], L[maxn], ans[maxn], num[maxn];
 7 int Cross(int x1, int y1, int x2, int y2)
 8 {
 9     return x1 * y2 - x2 * y1;
10 }
11 int main()
12 {
13     int n, m, x1, y1, x2, y2;
14     int a, b;
15     while(~scanf("%d",&n) && n)
16     {
17         scanf("%d%d%d%d%d", &m, &x1, &y1, &x2, &y2);
18         for(int i = 0;i < n;i++)
19         {
20             scanf("%d %d",&U[i], &L[i]);
21         }
22         sort(U, U + n);
23         sort(L, L + n);
24         for(int i = 0;i <= n;i++) ans[i] = num[i] = 0;
25         while(m--)
26         {
27             scanf("%d%d",&a, &b);
28             int i = 0;
29             for(i = 0;i < n;i++)
30             {
31                 if(Cross(a - L[i], b - y2, U[i] - L[i], y1 - y2) <= 0) break;
32             }
33             num[i]++;
34         }
35         for(int i = 0;i <= n;i ++) ans[num[i]] ++;
36         printf("Box\n");
37         for(int i = 1;i <= n;i++)if(ans[i]) printf("%d: %d\n",i, ans[i]);
38     }
39     return 0;
40 }
View Code

POJ 3304 Segments

题意:给出n条线段两个端点的坐标,问所有线段投影到一条直线上,如果这些所有投影至少相交于一点就输出Yes!,否则输出No!。

思路:枚举所有端点,判断与其他线段相不相交,至于为什么,画个图吧,反正我理解挺久的。

AC代码:

 1 #include<cstdio>
 2 #include<cmath>
 3 using namespace std;
 4 const double eps = 1e-8;
 5 struct Point{
 6     double x, y;
 7     Point(double _x = 0, double _y = 0):x(_x),y(_y){}
 8 };
 9 double Multi(Point p1, Point p2, Point p0) {
10     return (p1.x - p0.x) * (p2.y - p0.y) - (p1.y - p0.y) * (p2.x - p0.x);
11 }
12 int n;
13 struct Line{
14     Point a, b;
15 };
16 Line line[1000];
17 bool check(Point a, Point b)
18 {
19     if(fabs(a.x - b.x) < eps && fabs(a.y - b.y) < eps) return false;
20     for(int i = 0;i < n;i++)
21     {
22          if (Multi(line[i].a, b, a) * Multi(line[i].b, b, a) > 0) return false;
23 
24     }
25     return true;
26 }
27 int main()
28 {
29     int t;
30     scanf("%d",&t);
31     while(t--)
32     {
33         scanf("%d",&n);
34         double x1, y1, x2, y2;
35         for(int i = 0;i < n;i++)
36         {
37             scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
38             line[i].a = Point(x1, y1);
39             line[i].b = Point(x2, y2);
40         }
41         if(n == 1){ printf("Yes!\n");continue;}
42         bool flag = false;
43         for(int i = 0;i < n && !flag;i++)
44         {
45             if (check(line[i].a, line[i].b)) flag = true;
46             for(int j = i + 1;j < n && !flag;j++)
47             {
48                 if(check(line[i].a, line[j].a) ||
49                    check(line[i].a, line[j].b) ||
50                    check(line[i].b, line[j].a) ||
51                    check(line[i].b, line[j].b))
52                    flag = true;
53             }
54         }
55         if(flag) printf("Yes!\n");
56         else printf("No!\n");
57     }
58     return 0;
59 }
View Code

POJ 1269 Intersecting Lines

题意:俩条直线相交,相交则输出交点。

AC代码:

 1 #include<cstdio>
 2 #include<cmath>
 3 using namespace std;
 4 const double eps = 1e-8;
 5 struct Point{
 6     double x, y;
 7     Point(double _x = 0, double _y = 0):x(_x),y(_y){}
 8 }a, b, c, d;
 9 typedef Point Vector;
10 Vector operator - (Point A, Point B) { return Vector(A.x-B.x, A.y-B.y); }
11 Vector operator + (Vector A, Vector B) { return Vector(A.x+B.x, A.y+B.y); }
12 Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); }
13 Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); }
14 double Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x; }//叉积
15 Point GetLineIntersection(Point P, Vector v, Point Q, Vector w){
16     Vector u = P - Q;
17     double t = Cross(w,u)/Cross(v,w);
18     return P + v*t;
19 }
20 int main()
21 {
22     int n;
23     scanf("%d",&n);
24     printf("INTERSECTING LINES OUTPUT\n");
25     while(n--)
26     {
27         scanf("%lf %lf %lf %lf",&a.x, &a.y, &b.x, &b.y);
28         scanf("%lf %lf %lf %lf",&c.x, &c.y, &d.x, &d.y);
29         if(Cross(a - c, b - c) == 0 && Cross(a - d, b - d) == 0)
30             printf("LINE\n");
31         else if(Cross(a - b, c- d) == 0)
32             printf("NONE\n");
33         else
34         {
35             Point p = GetLineIntersection(a, a-b, c, c-d);
36             printf("POINT %.2f %.2f\n",p.x,p.y);
37         }
38     }
39     printf("END OF OUTPUT\n");
40     return 0;
41 }
View Code

POJ 1556 The Doors

题意:问你从(0,5) - > (10, 5)的最短路。

思路:枚举所有端点,如果确定和其他线段不规范相交,则加入这条路径,然后拿Floyd去跑最短路即可。

AC代码:

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const double eps = 1e-6;
 7 const int maxn = 1e3 + 5;
 8 const double inf = 1e20;
 9 struct Point{
10     double x, y;
11     Point(double _x = 0, double _y = 0):x(_x),y(_y){}
12 };
13 typedef Point Vector;
14 Vector operator - (Point A, Point B) { return Vector(A.x-B.x, A.y-B.y); }
15 Vector operator + (Vector A, Vector B) { return Vector(A.x+B.x, A.y+B.y); }
16 Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); }
17 Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); }
18 double Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x; }//²æ»ý
19 int dcmp(double x){
20     if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1;
21 }
22 double distant(Point a, Point b){
23     double x = a.x - b.x;
24     double y = a.y - b.y;
25     return sqrt(x*x + y*y);
26 }
27 bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2)
28 {
29     double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1),
30             c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1,a2 - b1);
31     return dcmp(c1)*dcmp(c2) < 0 && dcmp(c3)*dcmp(c4) < 0;
32 }
33 struct edge{
34     Point from, to;
35     edge(){}
36     edge(Point a, Point b){ from = a,to = b;}
37 };
38 Point p[maxn];
39 edge e[maxn];
40 double d[maxn][maxn];
41 int n, tot, cnt;
42 bool check(Point a, Point b)
43 {
44     for(int i = 0;i < tot;i++)
45         if(SegmentProperIntersection(a, b, e[i].from, e[i].to))
46         {
47             return false;
48         }
49 
50     return true;
51 }
52 int main()
53 {
54     while(~scanf("%d",&n) && n != -1)
55     {
56         tot = cnt = 0;
57         double x, y1, y2, y3, y4;
58         p[cnt++] = Point(0, 5);
59         for(int i = 0;i < n;i++)
60         {
61             scanf("%lf%lf%lf%lf%lf",&x, &y1, &y2, &y3, &y4);
62             p[cnt++] = Point(x, y1);
63             p[cnt++] = Point(x, y2);
64             p[cnt++] = Point(x, y3);
65             p[cnt++] = Point(x, y4);
66             e[tot++] = edge(Point(x, 0), Point(x, y1));
67             e[tot++] = edge(Point(x, y2), Point(x, y3));
68             e[tot++] = edge(Point(x, y4), Point(x, 10));
69         }
70         p[cnt++] = Point(10, 5);
71         for(int i = 0;i < cnt;i++)
72             for(int j = 0;j < cnt;j++)
73                 d[i][j] = inf;
74         for(int i = 0; i < cnt;i++)
75         {
76             for(int j = i + 1;j < cnt;j ++)
77             {
78                 if(fabs(p[i].x - p[j].x)< eps)continue;
79                 if(check(p[i], p[j]))
80                 {
81                     d[i][j] = d[j][i] = distant(p[i], p[j]);
82                 }
83             }
84         }
85         for(int k = 0;k < cnt;k++)
86             for(int i = 0;i < cnt;i++)
87                 for(int j = 0;j < cnt;j++)
88                 d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
89                 printf("%.2f\n",d[0][cnt - 1]);
90     }
91     return 0;
92 }
View Code

POJ 2653 Pick-up sticks

题意:筷子一根一根丢,问哪些筷子没被压着。

思路:所有和新加入的线段规范相交的线段标记,最后未标记的输出。

AC代码:

 

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const double eps = 1e-8;
 7 const int maxn = 1e5 + 5;
 8 const double inf = 1e20;
 9 struct Point{
10     double x, y;
11     Point(double _x = 0, double _y = 0):x(_x),y(_y){}
12 };
13 typedef Point Vector;
14 Vector operator - (Point A, Point B) { return Vector(A.x-B.x, A.y-B.y); }
15 Vector operator + (Vector A, Vector B) { return Vector(A.x+B.x, A.y+B.y); }
16 Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); }
17 Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); }
18 double Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x; }//²æ»ý
19 int dcmp(double x){
20     if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1;
21 }
22 double distant(Point a, Point b){
23     double x = a.x - b.x;
24     double y = a.y - b.y;
25     return sqrt(x*x + y*y);
26 }
27 bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2)
28 {
29     double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1),
30             c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1,a2 - b1);
31     return dcmp(c1)*dcmp(c2) < 0 && dcmp(c3)*dcmp(c4) < 0;
32 }
33 struct Line{
34     Point from, to;
35     Line(){}
36     Line(Point a, Point b){ from = a,to = b;}
37 };
38 Line line[maxn];
39 bool check(Line a, Line b)
40 {
41     return SegmentProperIntersection(a.from, a.to, b.from, b.to);
42 }
43 int vis[maxn];
44 int n, tot, cnt;
45 int main()
46 {
47     while(~scanf("%d",&n) && n)
48     {
49         double x1, y1, x2, y2;
50         for(int i = 0;i < n;i++)
51         {
52             scanf("%lf %lf %lf %lf",&x1, &y1, &x2, &y2);
53             line[i] = Line( Point(x1, y1), Point(x2, y2) );
54             vis[i] = 0;
55         }
56         for(int i = 0;i < n;i++){
57             for(int j = i + 1;j < n;j++)
58             {
59                 if(check(line[i], line[j]))
60                 {
61                     vis[i] = 1;break;
62                 }
63             }
64         }
65         printf("Top sticks: ");
66         bool flag = true;
67         for(int i = 0;i < n;i++)
68         {
69             if(!vis[i])
70             {
71                 if(flag) flag = false;
72                 else printf(", ");
73                 printf("%d",i + 1);
74             }
75         }
76         printf(".\n");
77     }
78     return 0;
79 }
View Code

 


POJ 1066 Treasure Hunt

题意:给你一个房间,房间内有很多墙,再给你个宝藏的坐标,你将从外面砸墙而入,问:你炸墙进去通过的最少的墙的1数目是多少。

思路:枚举线段的端点和宝藏位置的连线,看看和几个线段相交,要加上最外围的墙,所以ans从1开始。

AC代码:

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const double eps = 1e-8;
 7 const int maxn = 1e5 + 5;
 8 const int inf = 0x3f3f3f3f;
 9 struct Point{
10     double x, y;
11     Point(double _x = 0, double _y = 0):x(_x),y(_y){}
12 };
13 typedef Point Vector;
14 Vector operator - (Point A, Point B) { return Vector(A.x-B.x, A.y-B.y); }
15 Vector operator + (Vector A, Vector B) { return Vector(A.x+B.x, A.y+B.y); }
16 Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); }
17 Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); }
18 double Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x; }//²æ»ý
19 int dcmp(double x){
20     if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1;
21 }
22 double distant(Point a, Point b){
23     double x = a.x - b.x;
24     double y = a.y - b.y;
25     return sqrt(x*x + y*y);
26 }
27 bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2)
28 {
29     double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1),
30             c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1,a2 - b1);
31     return dcmp(c1)*dcmp(c2) < 0 && dcmp(c3)*dcmp(c4) < 0;
32 }
33 struct Line{
34     Point from, to;
35     Line(){}
36     Line(Point a, Point b){ from = a,to = b;}
37 };
38 Point p[maxn];
39 Line line[maxn];
40 int vis[maxn];
41 int n, tot, cnt;
42 int check(Point b, Point a)
43 {
44     int ans = 1;
45     for(int i = 0;i < tot;i++)
46     {
47         if(SegmentProperIntersection(line[i].from, line[i].to, b, a))
48             ans ++;
49     }
50     return ans;
51 }
52 int main()
53 {
54     while(~scanf("%d",&n))
55     {
56         if(n == 0)
57         {
58             printf("Number of doors = 1\n");return 0;
59         }
60         double x1, x2, y1, y2;
61         double x, y;
62         tot = cnt = 0;
63         int ans = inf;
64         for(int i = 0;i < n;i++)
65         {
66             scanf("%lf %lf %lf %lf",&x1 ,&y1, &x2, &y2);
67             p[cnt++] = Point(x1, y1);
68             p[cnt++] = Point(x2, y2);
69             line[tot++] = Line(Point(x1, y1), Point(x2, y2));
70         }
71         scanf("%lf %lf",&x, &y);
72         Point A = Point(x, y);
73         for(int i = 0;i < cnt;i++)
74         {
75             ans = min(ans, check(A, p[i]));
76         }
77         printf("Number of doors = %d\n",ans);
78     }
79     return 0;
80 }
View Code

 


POJ 1410 Intersection

题意:问直线和矩形是否相交。

思路:这题有坑,这矩形居然是实的,所以要特判一些情况。

AC代码:

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const double eps = 1e-8;
 7 const int maxn = 1e5 + 5;
 8 const int inf = 0x3f3f3f3f;
 9 struct Point{
10     double x, y;
11     Point(double _x = 0, double _y = 0):x(_x),y(_y){}
12 };
13 typedef Point Vector;
14 Vector operator - (Point A, Point B) { return Vector(A.x-B.x, A.y-B.y); }
15 Vector operator + (Vector A, Vector B) { return Vector(A.x+B.x, A.y+B.y); }
16 Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); }
17 Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); }
18 double Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x; }//²æ»ý
19 double Dot(Vector A, Vector B) { return A.x * B.x + A.y * B.y; }//点积
20 int dcmp(double x){
21     if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1;
22 }
23 double distant(Point a, Point b){
24     double x = a.x - b.x;
25     double y = a.y - b.y;
26     return sqrt(x*x + y*y);
27 }
28 bool SegmentProperIntersection(Point a1, Point a2, Point b1, Point b2)
29 {
30     double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1),
31             c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1,a2 - b1);
32     return dcmp(c1)*dcmp(c2) < 0 && dcmp(c3)*dcmp(c4) < 0;
33 }
34 struct Line{
35     Point from, to;
36     Line(){}
37     Line(Point a, Point b){ from = a,to = b;}
38 };
39 bool check(Line a, Line b){
40     return SegmentProperIntersection(a.from, a.to, b.from, b.to);
41 }
42 bool OnSegment(Point p, Point a1, Point a2){//判断端点在线段上
43     return dcmp(Cross(a1 - p, a2 - p)) == 0 && dcmp(Dot(a1 - p,a2 - p)) < 0;
44 }
45 bool check2(Point b, Line a){
46     return OnSegment(b, a.from, a.to);
47 }
48 int n;
49 int main()
50 {
51     scanf("%d",&n);
52     double x1, y1, x2, y2;
53     double x3, y3, x4, y4;
54     while(n--)
55     {
56         bool flag = false;
57         scanf("%lf %lf %lf %lf",&x1, &y1, &x2, &y2);
58         Point E = Point(x1, y1);
59         Point F = Point(x2, y2);
60         Line L = Line(E, F);
61         scanf("%lf %lf %lf %lf",&x3, &y3, &x4, &y4);
62         if(x3 > x4) swap(x3, x4);
63         if(y3 < y4) swap(y3, y4);
64         Point A = Point(x3, y3);
65         Point B = Point(x3, y4);
66         Point C = Point(x4, y4);
67         Point D = Point(x4, y3);
68         Line AB = Line(A, B);
69         Line CB = Line(C, B);
70         Line CD = Line(C, D);
71         Line AD = Line(A, D);
72         if(x1 >= x3 && x1 <= x4 && y1 <= y3 && y1 >= y4) flag = true;
73         if(check(AB, L) || check(CD, L) || check(AD, L) || check(CB, L))
74             flag = true;
75         if(check2(A, L) || check2(B, L) || check2(C, L) || check2(D, L))
76             flag = true;
77         if(check2(E, AB) || check2(E, CD) || check2(E, AD) || check2(E, CB))
78             flag = true;
79         if(check2(F, AB) || check2(F, CD) || check2(F, AD) || check2(F, CB))
80             flag = true;
81         if(flag) printf("T\n");
82         else printf("F\n");
83     }
84     return 0;
85 }
View Code

POJ 1696 Space Ant

题意:一只蚂蚁,只会向左转,现在给出平面上很多个点,求解一种走法,能使得蚂蚁能经过的点最多,每个顶点该蚂蚁只能经过一次,且所行走的路线不能发生交叉.

思路:这题用极角排序,边排序边输出orz。

AC代码:

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const double eps = 1e-8;
 7 const int maxn = 1e3+ 5;
 8 const int inf = 0x3f3f3f3f;
 9 struct Point{
10     double x, y;
11     int num;
12     Point(double _x = 0, double _y = 0):x(_x),y(_y){}
13 };
14 typedef Point Vector;
15 Vector operator - (Point A, Point B) { return Vector(A.x-B.x, A.y-B.y); }
16 Vector operator + (Vector A, Vector B) { return Vector(A.x+B.x, A.y+B.y); }
17 Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); }
18 Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); }
19 double Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x; }//²æ»ý
20 double Dot(Vector A, Vector B) { return A.x * B.x + A.y * B.y; }//点积
21 int dcmp(double x){
22     if(fabs(x) < eps) return 0; else return x < 0 ? -1 : 1;
23 }
24 double distant(Point a, Point b){
25     double x = a.x - b.x;
26     double y = a.y - b.y;
27     return sqrt(x*x + y*y);
28 }
29 Point p[maxn];
30 int pos;
31 bool cmp(const Point a, const Point b){
32     int temp = Cross(p[pos] - a,p[pos] - b);
33     if(temp > 0) return  true;
34     else if(temp == 0 && distant(p[pos], a) < distant(p[pos], b))
35         return true;
36     return false;
37 }
38 int n;
39 int main()
40 {
41     int t;
42     scanf("%d",&t);
43     while (t--){
44         scanf("%d",&n);
45         for (int i = 0; i < n; ++i) {
46             scanf("%d %lf %lf",&p[i].num, &p[i].x, &p[i].y);
47             if(p[i].y < p[0].y || (p[i].y == p[0].y && p[i].x < p[0].x))
48                 swap(p[i],p[0]);
49         }
50         pos = 0;
51         printf("%d",n);
52         for(int i = 1;i < n;++i){
53             sort(p + i,p + n, cmp);
54             pos++;
55         }
56         for (int i = 0; i < n; ++i) {
57             printf(" %d",p[i].num);
58         }
59         printf("\n");
60     }
61     return 0;
62 }
View Code

POJ 3347 Kadj Squares

思路:这题在网上扒了一个不是几何的做法,具体看代码吧。

AC代码:

 1 #include<cstdio>
 2 #include<cmath>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 const int maxn = 505;
 7 struct node{
 8     int l, r, len;
 9 };
10 node a[maxn];
11 int n;
12 int main()
13 {
14     while(~scanf("%d",&n) && n)
15     { 
16         memset(a,0,sizeof(a));
17         for(int i = 0;i < n;i++)
18         {
19             scanf("%d",&a[i].len);
20             for(int j = 0;j < i;j ++)
21             {
22                 a[i].l = max(a[i].l, a[j].r - abs(a[i].len - a[j].len));
23             }
24             a[i].r = a[i].l + 2*a[i].len;
25         }
26         for(int i = 0;i < n;i++)
27         {
28             for(int j = 0;j < i;j ++)
29             {
30                 if(a[i].l < a[j].r)
31                 {
32                     if(a[j].len < a[i].len) a[j].r = a[i].l;
33                     else a[i].l = a[j].r;
34                 }
35             }
36         }
37         bool flag = false;
38         for(int i = 0;i < n;i++)
39         {
40             if(a[i].l < a[i].r)
41             {
42                 if(!flag) printf("%d",i + 1),flag = true;
43                 else printf(" %d",i+1);
44             }
45         }
46         printf("\n");
47     }
48     return 0;
49 }
View Code

POJ 2826 An Easy Problem?!

题意:两根木棍,摆放的方式由题目给出,问接到雨水的量是多少。(注意是平面,只要考虑面积)

思路:这题不看题解真想不到,简直天坑,点题解一看图就懂了,太多特殊情况了。最后所有都特判了,结果答案还要加个eps才能过orz,醉了!

AC代码:

  1 #include<cmath>
  2 #include<cstdio>
  3 #include<algorithm>
  4 using namespace std;
  5 const double eps = 1e-12;
  6 int sgn(double x){
  7     if(fabs(x) < eps) return 0;
  8     else return x < 0 ? -1 : 1;
  9 }
 10 struct Point{
 11     double x, y;
 12     Point(){}
 13     Point(double _x, double _y){
 14         x = _x, y = _y;
 15     }
 16     Point operator - (const Point &b){
 17         return Point(x - b.x, y - b.y);
 18     }
 19     double operator * (const Point &b){
 20         return x*b.x + y*b.y;
 21     }
 22     double operator ^ (const Point &b){
 23         return x*b.y - y* b.x;
 24     }
 25 };
 26 struct Line{
 27     Point s, e;
 28     Line(){}
 29     Line(Point _s, Point _e){
 30         s = _s, e = _e;
 31     }
 32     int segcrossing(Line v)
 33     {
 34         int d1 = sgn((e - s)^(v.s - s));
 35         int d2 = sgn((e - s)^(v.e - s));
 36         int d3 = sgn((v.e - v.s)^(s - v.s));
 37         int d4 = sgn((v.e - v.s)^(e - v.s));
 38         if( (d1^d2) == -2 && (d3^d4) == -2 )return 2;
 39         return
 40         (d1 == 0 && sgn((v.s - s)*(v.s - e)) <= 0) ||
 41         (d2 == 0 && sgn((v.e - s)*(v.e - e)) <= 0) ||
 42         (d3 == 0 && sgn((s - v.s)*(s - v.e)) <= 0) ||
 43         (d4 == 0 && sgn((e - v.s)*(e - v.e)) <= 0);
 44     }
 45     Point crosspoint(Line v){
 46         double a1 = (v.e - v.s)^(s - v.s);
 47         double a2 = (v.e - v.s)^(e - v.s);
 48         return Point((s.x*a2 - e.x*a1)/(a2 - a1),(s.y*a2 - e.y*a1)/(a2 - a1));
 49     }
 50 };
 51 int main()
 52 {
 53     double x1, x2, x3, x4, y1, y2, y3, y4;
 54     Line A, B;
 55     int t;
 56     scanf("%d",&t);
 57     while(t--){
 58         scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
 59         scanf("%lf%lf%lf%lf", &x3, &y3, &x4, &y4);
 60         A = Line(Point(x1, y1),Point(x2, y2));
 61         B = Line(Point(x3, y3),Point(x4, y4));
 62         if(sgn(A.s.y - A.e.y) == 0 || sgn(B.s.y - B.e.y) == 0)
 63         {
 64             printf("0.00\n");
 65             continue;
 66         }
 67         if(sgn((A.s - A.e)^(B.s - B.e)) == 0)
 68         {
 69             printf("0.00\n");
 70             continue;
 71         }
 72         //高的点放 s.y下面会用到
 73         if(sgn(A.s.y - A.e.y) < 0) swap(A.s, A.e);
 74         if(sgn(B.s.y - B.e.y) < 0) swap(B.s, B.e);
 75 
 76         if(A.segcrossing(B) == 0)
 77         {
 78             printf("0.00\n");
 79             continue;
 80         }
 81         //口被封掉的情况
 82         if(B.segcrossing(Line(A.s,Point(A.s.x,100000))) )
 83         {
 84             printf("0.00\n");
 85             continue;
 86         }
 87         if(A.segcrossing(Line(B.s,Point(B.s.x,100000))) )
 88         {
 89             printf("0.00\n");
 90             continue;
 91         }
 92         Point C = A.crosspoint(B);
 93         //printf("%f %f",C.x,C.y);
 94         double ans1,ans2;
 95         Point D = A.crosspoint(Line(Point(100000,B.s.y),B.s));
 96         //printf("%f %f",D.x,D.y);
 97         ans1 = fabs( (B.s - C) ^ (D - C) )/2.0;
 98         Point E = B.crosspoint(Line(Point(100000,A.s.y),A.s));
 99         ans2 = fabs( (A.s - C) ^ (E - C) )/2.0;
100         double ans = min(ans1,ans2);
101         printf("%.2f\n",ans +eps);
102     }
103     return 0;
104 }
View Code

POJ 1039 Pipe

题意:有一宽度为1的折线管道,上面顶点为(xi,yi),所对应的下面顶点为(xi,yi-1),假设管道都是不透明的,不反射的,光线从左边入口处的(x1,y1),(x1,y1-1)之间射入,向四面八方传播,求解光线最远能传播到哪里(取x坐标)或者是否能穿透整个管道。

思路:因为WA到自闭。于是改用kuangbin大佬的板子,于是就过了,orz!板子很重要。能到达最远的光线一定是某一上端点和某一下端点的连线,枚举判断。

AC代码:

 1 #include<cmath>
 2 #include<cstdio>
 3 #include<algorithm>
 4 using namespace std;
 5 const double eps = 1e-8;
 6 const int maxp = 50;
 7 int sgn(double x){
 8     if(fabs(x) < eps) return 0;
 9     else return x < 0 ? -1 : 1;
10 }
11 struct Point{
12     double x, y;
13     Point(){}
14     Point(double _x, double _y){
15             x = _x, y = _y;
16     }
17     Point operator -(const Point &b)const{
18         return Point(x - b.x, y - b.y);
19     }
20     double operator *(const Point &b)const{
21         return x*b.x + y*b.y;
22     }
23     double operator ^(const Point &b)const{
24         return x*b.y - y*b.x;
25     }
26     bool operator == (Point b) const{
27         return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
28     }
29     bool operator < (Point b)const{
30         return sgn(x - b.x) == 0 ? sgn(y - b.y < 0) : x < b.x;
31     }
32 };
33 struct Line{
34     Point s, e;
35     Line(){}
36     Line(Point _s, Point _e){s = _s, e = _e;}
37     bool operator == (Line v){
38         return (s == v.s) && (e == v.e);
39     }
40     int linecrossing(Line v){
41         int d1 = sgn((e - s) ^ (v.s - s));
42         int d2 = sgn((e - s) ^ (v.e - s));
43         if( (d1 ^ d2) == -2) return 2;
44         else return (d1 == 0) || (d2 == 0);
45     }
46     Point crosspoint(Line v){
47         double a1 = (v.e - v.s)^(s - v.s);
48         double a2 = (v.e - v.s)^(e - v.s);
49         return Point((s.x*a2 - e.x*a1)/(a2 - a1),(s.y*a2 - e.y*a1)/(a2 - a1));
50     }
51 };
52 Point up[maxp], down[maxp];
53 int main()
54 {
55     int n;
56     Line A;
57     while(~scanf("%d",&n) && n)
58     {
59         for(int i = 0;i < n;i++)
60         {
61             scanf("%lf %lf",&up[i].x, &up[i].y);
62             down[i].x = up[i].x, down[i].y = up[i].y - 1;
63         }
64         bool flag = false;
65         double ans = -100000000.0;
66         for(int i = 0;i < n;i++)
67         {
68             for(int j = 0;j < n;j++)
69             {
70                 int k;
71                 A = Line(up[i], down[j]);
72                 for(k = 0;k < n;k++){
73                     if(!A.linecrossing(Line(up[k], down[k])) )
74                     {
75                         break;
76                     }
77                 }
78                 if(k >= n){flag = true;break;}
79                 if(k > max(i, j))
80                 {
81                     if(A.linecrossing(Line(up[k], up[k-1])))
82                     {
83                         Point x = A.crosspoint(Line(up[k], up[k-1]));
84                         ans = max(ans,x.x);
85                     }
86                     if(A.linecrossing(Line(down[k], down[k-1])))
87                     {
88                         Point x = A.crosspoint(Line(down[k], down[k-1]));
89                         ans = max(ans,x.x);
90                     }
91                 }
92                 if(flag) break;
93             }
94         }
95         if(flag) printf("Through all the pipe.\n");
96         else printf("%.2f\n",ans + eps);
97     }
98     return 0;
99 }
View Code

POJ 3449 Geometric Shapes

POJ 1584 A Round Peg in a Ground Hole

 

转载于:https://www.cnblogs.com/Carered/p/11406236.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值