POJ 1066 Treasure Hunt

题目大意:

一个正方形的墓葬内有n堵墙,每堵墙的两个顶点都在正方形的边界上,现在这些墙将墓葬分割成了很多小空间,

已知正方形内的一个点上存在宝藏,现在我们要在正方形的外面去得到宝藏,对于每个小空间,我们可以炸开它的任意一条边的中点,

现在给出每堵墙的两个节点的坐标和宝藏的坐标,问如果要得到宝藏,需要炸的墙数最少是多少。

 

输入:

输入将包括一个案例。第一行是一个整数N(0≤N≤30)指定内墙的数量,其次是N行包含每个墙x1 y1 x2 y2整数点

内墙总是从一个外墙延伸到另一个外墙,并且布置成在任何点都不超过两个墙相交。你可以假设没有两个给定的墙重合。

输出
用下面所示的格式打印一行,列出需要创建的最小门数。

 

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

题解:

枚举正方形边界上的点作为进入正方形的节点,由这个点向宝藏连出一条线段,这条线段和多少个墙相交,那么就需要炸坏多少个墙,找出一个最小的值。

原因:因为每堵墙的两个节点都在边界上,所以如果和墙相交,那么就一定要跨过这道墙,所以需要炸掉它。

一定要是规范相交,因为如果枚举的点如果是一堵墙的节点,那么这堵墙是不应该被计算的。

事实上从一个点到终点不可能“绕过”围墙,只能穿过去,所以门是否开在中点是无所谓的,只要求四周线段中点到终点的线段与墙的最少交点个数即可。实际上,只需判断四周围墙的所有点与终点的连线与内墙的最少交点加一

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<cmath>
 6 using namespace std;
 7 double x1[1001],y11[1001],x2[1001],y2[1001],sx,sy;
 8 int n,ans;
 9 bool exam(double x3,double y3,int i)
10 {
11     double dx=x3-x1[i],dy=y3-y11[i];
12     double px=x2[i]-x1[i],py=y2[i]-y11[i];
13     double fx=sx-x1[i],fy=sy-y11[i];
14     if ((dx*py-dy*px)*(px*fy-py*fx)<=0) return 0;
15     dx=x1[i]-x3;dy=y11[i]-y3;
16     px=sx-x3;py=sy-y3;
17     fx=x2[i]-x3;fy=y2[i]-y3;
18     if ((dx*py-dy*px)*(px*fy-py*fx)<=0) return 0;
19 return 1;
20 }
21 void solve(double x,double y)
22 {int s=0,i;
23     for (i=1;i<=n;i++)
24     {
25         if (exam(x,y,i)) s++;
26     }
27     ans=min(ans,s);
28 }
29 int main()
30 {int i;
31     cin>>n;
32     ans=n;
33     for (i=1;i<=n;i++)
34     {
35         scanf("%lf%lf%lf%lf",&x1[i],&y11[i],&x2[i],&y2[i]);
36     }
37     scanf("%lf%lf",&sx,&sy);
38      for (i=0;i<=100;i++)
39      {
40           solve(0,i);
41           solve(100,i);
42           solve(i,0);
43           solve(i,100);
44      }
45      ans++;
46      cout<<"Number of doors = ";
47      cout<<ans<<endl;
48 }

 

 

 

posted @ 2017-08-01 18:24  Z-Y-Y-S  阅读(192)  评论(0编辑  收藏  举报