1. 程式人生 > >Treasure Hunt

Treasure Hunt

Treasure Hunt

http://poj.org/problem?id=1066

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 8233   Accepted: 3402

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

East Central North America 1999

 

列舉邊界上的點,要注意,列舉的步長為1會wa,步長要0.5= =

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<vector>
  6 #include<algorithm>
  7 using namespace std;
  8 const double eps=1e-8;
  9 const double INF=1e20;
 10 const double PI=acos(-1.0);
 11 const int maxp=1010;
 12 int sgn(double x){
 13     if(fabs(x)<eps) return 0;
 14     if(x<0) return -1;
 15     else return 1;
 16 }
 17 
 18 double hypot(double x,double y){
 19     return sqrt(x*x+y*y);
 20 }
 21 
 22 inline double sqr(double x){return x*x;}
 23 struct Point{
 24     double x,y;
 25     Point(){}
 26     Point(double _x,double _y){
 27         x=_x;
 28         y=_y;
 29     }
 30     void input(){
 31         scanf("%lf %lf",&x,&y);
 32     }
 33     void output(){
 34         printf("%.2f %.2f\n",x,y);
 35     }
 36     bool operator == (const Point &b)const{
 37         return sgn(x-b.x) == 0 && sgn(y-b.y)== 0;
 38     }
 39     bool operator < (const Point &b)const{
 40         return sgn(x-b.x)==0?sgn(y-b.y)<0:x<b.x;
 41     }
 42     Point operator - (const Point &b)const{
 43         return Point(x-b.x,y-b.y);
 44     }
 45     //叉積
 46     double operator ^ (const Point &b)const{
 47         return x*b.y-y*b.x;
 48     }
 49     //點積
 50     double operator * (const Point &b)const{
 51         return x*b.x+y*b.y;
 52     }
 53     //返回長度
 54     double len(){
 55         return hypot(x,y);
 56     }
 57     //返回長度的平方
 58     double len2(){
 59         return x*x+y*y;
 60     }
 61     //返回兩點的距離
 62     double distance(Point p){
 63         return hypot(x-p.x,y-p.y);
 64     }
 65     Point operator + (const Point &b)const{
 66         return Point(x+b.x,y+b.y);
 67     }
 68     Point operator * (const double &k)const{
 69         return Point(x*k,y*k);
 70     }
 71     Point operator / (const double &k)const{
 72         return Point(x/k,y/k);
 73     }
 74 
 75     //計算pa和pb的夾角
 76     //就是求這個點看a,b所成的夾角
 77     ///LightOJ1202
 78     double rad(Point a,Point b){
 79         Point p=*this;
 80         return fabs(atan2(fabs((a-p)^(b-p)),(a-p)*(b-p)));
 81     }
 82     //化為長度為r的向量
 83     Point trunc(double r){
 84         double l=len();
 85         if(!sgn(l)) return *this;
 86         r/=l;
 87         return Point(x*r,y*r);
 88     }
 89     //逆時針轉90度
 90     Point rotleft(){
 91         return Point(-y,x);
 92     }
 93     //順時針轉90度
 94     Point rotright(){
 95         return Point(y,-x);
 96     }
 97     //繞著p點逆時針旋轉angle
 98     Point rotate(Point p,double angle){
 99         Point v=(*this) -p;
100         double c=cos(angle),s=sin(angle);
101         return Point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c);
102     }
103 };
104 
105 struct Line{
106     Point s,e;
107     Line(){}
108     Line(Point _s,Point _e){
109         s=_s;
110         e=_e;
111     }
112     bool operator==(Line v){
113         return (s==v.s)&&(e==v.e);
114     }
115     //根據一個點和傾斜角angle確定直線,0<=angle<pi
116     Line(Point p,double angle){
117         s=p;
118         if(sgn(angle-PI/2)==0){
119             e=(s+Point(0,1));
120         }
121         else{
122             e=(s+Point(1,tan(angle)));
123         }
124     }
125     //ax+by+c=0;
126     Line(double a,double b,double c){
127         if(sgn(a)==0){
128             s=Point(0,-c/b);
129             e=Point(1,-c/b);
130         }
131         else if(sgn(b)==0){
132             s=Point(-c/a,0);
133             e=Point(-c/a,1);
134         }
135         else{
136             s=Point(0,-c/b);
137             e=Point(1,(-c-a)/b);
138         }
139     }
140     void input(){
141         s.input();
142         e.input();
143     }
144     void adjust(){
145         if(e<s) swap(s,e);
146     }
147     //求線段長度
148     double length(){
149         return s.distance(e);
150     }
151     //返回直線傾斜角 0<=angle<pi
152     double angle(){
153         double k=atan2(e.y-s.y,e.x-s.x);
154         if(sgn(k)<0) k+=PI;
155         if(sgn(k-PI)==0) k-=PI;
156         return k;
157     }
158     //點和直線的關係
159     //1 在左側
160     //2 在右側
161     //3 在直線上
162     int relation(Point p){
163         int c=sgn((p-s)^(e-s));
164         if(c<0) return 1;
165         else if(c>0) return 2;
166         else return 3;
167     }
168     //點線上段上的判斷
169     bool pointonseg(Point p){
170         return sgn((p-s)^(e-s))==0&&sgn((p-s)*(p-e))<=0;
171     }
172     //兩向量平行(對應直線平行或重合)
173     bool parallel(Line v){
174         return sgn((e-s)^(v.e-v.s))==0;
175     }
176     //兩線段相交判斷
177     //2 規範相交
178     //1 非規範相交
179     //0 不相交
180     int segcrossseg(Line v){
181         int d1=sgn((e-s)^(v.s-s));
182         int d2=sgn((e-s)^(v.e-s));
183         int d3=sgn((v.e-v.s)^(s-v.s));
184         int d4=sgn((v.e-v.s)^(e-v.s));
185         if((d1^d2)==-2&&(d3^d4)==-2) return 2;
186         return (d1==0&&sgn((v.s-s)*(v.s-e))<=0||
187                 d2==0&&sgn((v.e-s)*(v.e-e))<=0||
188                 d3==0&&sgn((s-v.s)*(s-v.e))<=0||
189                 d4==0&&sgn((e-v.s)*(e-v.e))<=0);
190     }
191     //直線和線段相交判斷
192     //-*this line -v seg
193     //2 規範相交
194     //1 非規範相交
195     //0 不相交
196     int linecrossseg(Line v){
197         int d1=sgn((e-s)^(v.s-s));
198         int d2=sgn((e-s)^(v.e-s));
199         if((d1^d2)==-2) return 2;
200         return (d1==0||d2==0);
201     }
202     //兩直線關係
203     //0 平行
204     //1 重合
205     //2 相交
206     int linecrossline(Line v){
207         if((*this).parallel(v))
208             return v.relation(s)==3;
209         return 2;
210     }
211     //求兩直線的交點
212     //要保證兩直線不平行或重合
213     Point crosspoint(Line v){
214         double a1=(v.e-v.s)^(s-v.s);
215         double a2=(v.e-v.s)^(e-v.s);
216         return Point((s.x*a2-e.x*a1)/(a2-a1),(s.y*a2-e.y*a1)/(a2-a1));
217     }
218     //點到直線的距離
219     double dispointtoline(Point p){
220         return fabs((p-s)^(e-s))/length();
221     }
222     //點到線段的距離
223     double dispointtoseg(Point p){
224         if(sgn((p-s)*(e-s))<0||sgn((p-e)*(s-e))<0)
225             return min(p.distance(s),p.distance(e));
226         return dispointtoline(p);
227     }
228     //返回線段到線段的距離
229     //前提是兩線段不相交,相交距離就是0了
230     double dissegtoseg(Line v){
231         return min(min(dispointtoseg(v.s),dispointtoseg(v.e)),min(v.dispointtoseg(s),v.dispointtoseg(e)));
232     }
233     //返回點P在直線上的投影
234     Point lineprog(Point p){
235         return s+(((e-s)*((e-s)*(p-s)))/((e-s).len2()));
236     }
237     //返回點P關於直線的對稱點
238     Point symmetrypoint(Point p){
239         Point q=lineprog(p);
240         return Point(2*q.x-p.x,2*q.y-p.y);
241     }
242 };
243 
244 Line L[1005];
245 int n;
246 
247 bool Check(Line a,Line b){
248     if(sgn((a.s-a.e)^(b.s-a.e))*sgn((a.s-a.e)^(b.e-a.e))>0) return false;
249     if(sgn((b.s-b.e)^(a.s-b.e))*sgn((b.s-b.e)^(a.e-b.e))>0) return false;
250     if(sgn(max(a.s.x,a.e.x)-min(b.s.x,b.e.x))>=0&&sgn(max(b.s.x,b.e.x)-min(a.s.x,a.e.x))>=0
251      &&sgn(max(a.s.y,a.e.y)-min(b.s.y,b.e.y))>=0&&sgn(max(b.s.y,b.e.y)-min(a.s.y,a.e.y))>=0)
252         return true;
253     else return false;
254 }
255 
256 
257 double mp[115][115];
258 
259 int co;
260 
261 int panduan(Line a){
262     int sum=0;
263     for(int i=1;i<=n;i++){
264         if(Check(a,L[i])){
265             sum++;
266         }
267     }
268     return sum;
269 }
270 
271 int main(){
272 
273     while(~scanf("%d",&n)){
274         for(int i=1;i<=n;i++){
275             scanf("%lf %lf %lf %lf",&L[i].s.x,&L[i].s.y,&L[i].e.x,&L[i].e.y);
276         }
277         int ans=0x3f3f3f3f;
278         Point goal;
279         scanf("%lf %lf",&goal.x,&goal.y);
280         Line tmp;
281         tmp.s=goal;
282         for(double i=0;i+eps<=100;i+=0.5){
283             tmp.e.x=0,tmp.e.y=i;
284             ans=min(ans,panduan(tmp));
285             tmp.e.x=i,tmp.e.y=0;
286             ans=min(ans,panduan(tmp));
287             tmp.e.x=100,tmp.e.y=i;
288             ans=min(ans,panduan(tmp));
289             tmp.e.x=i,tmp.e.y=100;
290             ans=min(ans,panduan(tmp));
291         }
292         printf("Number of doors = %d\n",ans+1);
293     }
294 
295     return 0;
296 }
View Code