poj1066 Treasure Hunt【计算几何】

Treasure Hunt
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 8192   Accepted: 3376

Description

Archeologists from the Antiquities and Curios Museum (ACM) have flown to Egypt to examine the great pyramid of Key-Ops. Using state-of-the-art technology they are able to determine that the lower floor of the pyramid is constructed from a series of straightline walls, which intersect to form numerous enclosed chambers. Currently, no doors exist to allow access to any chamber. This state-of-the-art technology has also pinpointed the location of the treasure room. What these dedicated (and greedy) archeologists want to do is blast doors through the walls to get to the treasure room. However, to minimize the damage to the artwork in the intervening chambers (and stay under their government grant for dynamite) they want to blast through the minimum number of doors. For structural integrity purposes, doors should only be blasted at the midpoint of the wall of the room being entered. You are to write a program which determines this minimum number of doors. 
An example is shown below: 

Input

The input will consist of one case. The first line will be an integer n (0 <= n <= 30) specifying number of interior walls, followed by n lines containing integer endpoints of each wall x1 y1 x2 y2 . The 4 enclosing walls of the pyramid have fixed endpoints at (0,0); (0,100); (100,100) and (100,0) and are not included in the list of walls. The interior walls always span from one exterior wall to another exterior wall and are arranged such that no more than two walls intersect at any point. You may assume that no two given walls coincide. After the listing of the interior walls there will be one final line containing the floating point coordinates of the treasure in the treasure room (guaranteed not to lie on a wall).

Output

Print a single line listing the minimum number of doors which need to be created, in the format shown below.

Sample Input

7 
20 0 37 100 
40 0 76 100 
85 0 0 75 
100 90 0 90 
0 71 100 61 
0 14 100 38 
100 47 47 100 
54.5 55.4 

Sample Output

Number of doors = 2 

Source

题意:

一个正方形中有n面墙,告诉你一个宝藏所在的坐标。问最少要砸穿多少墙才能到达宝藏。

思路:

枚举宝藏坐标和所有的墙的端点构成一个线段。判断这个线段和多少墙相交,因为这个就是从某一个点进入的最短距离,相交的个数就是穿墙数。

这个端点就是最开始进入的点。

相当于那些墙的端点把外围墙划分成了很多区域,我们从某一个点进去。两个端点之间任何一个位置进去都是一样的,所以枚举端点就行了。

找一个最小值就行了。要注意有可能是从角进去的。

刚开始inter函数写错了。

  1 #include <iostream>
  2 #include <set>
  3 #include <cmath>
  4 #include <stdio.h>
  5 #include <cstring>
  6 #include <algorithm>
  7 #include <vector>
  8 #include <queue>
  9 #include <map>
 10 //#include <bits/stdc++.h>
 11 using namespace std;
 12 typedef long long LL;
 13 #define inf 0x7f7f7f7f
 14 
 15 const double eps = 1e-8;
 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 
 23 struct point{
 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     point operator +(const point &b)const
 36     {
 37         return point(x + b.x, y + b.y);
 38     }
 39     point operator /(double d)const
 40     {
 41         return point(x / d, y / d);
 42     }
 43     double operator ^(const point &b)const
 44     {
 45         return x * b.y - y * b.x;
 46     }
 47     double operator *(const point &b)const
 48     {
 49         return x * b.x + y * b.y;
 50     }
 51     //绕原点旋转B
 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     point s, e;
 61     double k;
 62     line(){}
 63     line(point _s, point _e)
 64     {
 65         s = _s;
 66         e = _e;
 67         k = atan2(e.y - s.y, e.x - s.x);
 68     }
 69     pair<int, point>operator &(const line &b)const
 70     {
 71         point res = s;
 72         if(sgn((s - e) ^ (b.s - b.e)) == 0){
 73             if(sgn((s - b.e) ^ (b.s - b.e)) == 0){
 74                 return make_pair(0, res);
 75             }
 76             else return make_pair(1, res);
 77         }
 78         double t = ((s - b.s) ^ (b.s - b.e)) / ((s - e) ^ (b.s - b.e));
 79         res.x += (e.x - s.x) * t;
 80         res.y += (e.y - s.y) * t;
 81         return make_pair(2, res);
 82     }
 83 };
 84 
 85 double dist(point a, point b)
 86 {
 87     return sqrt((a - b) * (a - b));
 88 }
 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.s)^(l1.e-l1.s))*sgn((l2.e-l1.s)^(l1.e-l1.s)) <= 0 &&
 99         sgn((l1.s-l2.s)^(l2.e-l1.s))*sgn((l1.e-l2.s)^(l2.e-l2.s)) <= 0;
100 }
101 
102 const int maxn = 110;
103 line l[maxn];
104 point treasure, p[maxn];
105 int n;
106 
107 int main()
108 {
109     l[1] = line(point(0, 0), point(0, 100));
110     l[2] = line(point(0,100), point(100, 100));
111     l[3] = line(point(100, 100), point(100, 0));
112     l[4] = line(point(100, 0), point(0, 0));
113     while(scanf("%d", &n) != EOF){
114         for(int i = 5; i <= n + 4; i++){
115             scanf("%lf%lf%lf%lf", &l[i].s.x, &l[i].s.y, &l[i].e.x, &l[i].e.y);
116             //[2 * i - 1] = l[i].s;
117             //p[2 * i] = l[i].e;
118         }
119         scanf("%lf%lf", &treasure.x, &treasure.y);
120 
121         int ans = inf;
122         for(int i = 1; i <= 4; i++){
123             line l1 = line(treasure, l[i].s), l2 = line(treasure, l[i].e);
124             int cnt1 = 0, cnt2 = 0;
125             for(int j = 5; j <= n + 4; j++){
126                 if(inter(l1, l[j])){
127                     cnt1++;
128                     //cout<<cnt1<<endl;
129                 }
130                 if(inter(l2, l[j])){
131                     cnt2++;
132                     //cout<<cnt1<<endl;
133                 }
134             }
135             ans = min(ans, cnt1 + 1);
136             ans = min(ans, cnt2 + 1);
137         }
138         for(int i = 5; i <= n + 4; i++){
139             line l1 = line(treasure, l[i].s), l2 = line(treasure, l[i].e);
140             int cnt1 = 0, cnt2 = 0;
141             for(int j = 5; j <= n + 4; j++){
142                 if(inter(l1, l[j])){
143                     cnt1++;
144                 }
145                 if(inter(l2, l[j])){
146                     cnt2++;
147                 }
148             }
149             ans = min(ans, cnt1);
150             ans = min(ans, cnt2);
151         }
152         /*for(int i = 1; i <= n * 2; i++){
153             line l1 = line(treasure, p[i]);
154             int cnt = 0;
155             for(int j = 1; j <= n; j++){
156                 if(inter(l1, l[j])){
157                     cnt++;
158                 }
159             }
160             ans = min(ans, cnt);
161             //cout<<ans<<endl;
162         }
163         line l1 = line(treasure, point(0, 0));
164         int cnt = 0;
165         for(int i = 1; i <= n; i++){
166             if(inter(l1, l[i])){
167                 cnt++;
168             }
169         }
170         ans = min(ans, cnt + 1);
171         cnt = 0;
172         l1 = line(treasure, point(0, 100));
173         for(int i = 1; i <= n; i++){
174             if(inter(l1, l[i])){
175                 cnt++;
176             }
177         }
178         ans = min(ans, cnt + 1);
179         cnt = 0;
180         l1 = line(treasure, point(100, 0));
181         for(int i = 1; i <= n; i++){
182             if(inter(l1, l[i])){
183                 cnt++;
184             }
185         }
186         ans = min(ans, cnt + 1);
187         cnt = 0;
188         l1 = line(treasure, point(100, 100));
189         for(int i = 1; i <= n; i++){
190             if(inter(l1, l[i])){
191                 cnt++;
192             }
193         }
194         ans = min(ans, cnt + 1);*/
195         printf("Number of doors = %d
", ans);
196     }
197     return 0;
198 }
原文地址:https://www.cnblogs.com/wyboooo/p/9896364.html