http://poj.org/problem?id=1066
大意; 问在房间中有一份宝藏,但是房间中有一些隔板,问最少需要通过多少隔板
思路: 链接宝藏与爆破地点,枚举每一条直线寻找最少破坏的隔板。。
1 #include <iostream>
2 #include <algorithm>
3 #include <cmath>
4 using namespace std;
5 const int maxn = 110;
6 const double eps = 1e-8;
7
8 double fix_double(double x){
9 return fabs(x)<eps?0.0:x;
10 }
11
12 int sign(double x){
13 return x<-eps?-1:x>eps;
14 }
15
16 struct point {
17 double x,y;
18 //point (){}
19 point(double x=0,double y=0):x(x),y(y){}
20 point operator - (const point b) const {
21 return point(x-b.x,y-b.y);
22 }
23 };
24
25 struct line {
26 point a,b;
27 line(){}
28 line(point _a,point _b){
29 a = _a;
30 b = _b;
31 }
32 };
33 double dot(point o,point a,point b){
34 point oa = a-o;
35 point ob = b-o;
36 return oa.x*ob.x+oa.y*ob.y;
37 }
38
39 double cross(point o,point a,point b){
40 point oa = a-o;
41 point ob = b-o;
42 return oa.x*ob.y-ob.x*oa.y;
43 }
44
45 int n;
46 line ln[maxn];
47 point tr,pt[maxn*10];//tr为宝藏,pt为边上的点
48
49 double dis(point a,point b){
50 return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
51 }
52
53 bool cmp(point a,point b){ //数据太弱这样也过了。。。
54 point zero = point(0,0);
55 int ans = sign(cross(zero,a,b));
56 if(ans==0) return dis(zero,a)+eps<dis(zero,b);
57 return ans>0;
58 }
59 //0不在,1,在线段内,2在断点处
60 int in_line(point pt, line li){
61 if(sign(cross(pt,li.a,li.b))) return 0;
62 int ans = sign(dot(pt,li.a,li.b));
63 return ans==0?2:ans<0;//cos钝角小于0.。
64 }
65
66 //0不相交,1规范相交,2交与短点,3,有重合部分
67 int across(line ab,line cd){
68 if(max(ab.a.x,ab.b.x)<min(cd.a.x,cd.b.x)||max(ab.a.y,ab.b.y)<min(cd.a.y,cd.b.y)||max(cd.a.x,cd.b.x)<min(ab.a.x,ab.b.x)||max(cd.a.y,cd.b.y)<min(ab.a.y,ab.b.y))
69 return 0;
70 int ab_cd = sign(cross(ab.a,ab.b,cd.a))*sign(cross(ab.a,ab.b,cd.b));
71 int cd_ab = sign(cross(cd.a,cd.b,ab.a))*sign(cross(cd.a,cd.b,ab.b));
72 if(ab_cd==0&&cd_ab==0&&(in_line(ab.a,cd)==1||in_line(ab.b,cd)==1))
73 return 3;
74 if(ab_cd<0)
75 return cd_ab==0?2:cd_ab<0;
76 else if(ab_cd==0)
77 return cd_ab<=0?2:0;
78 return 0;
79 }
80
81 int solve(){
82 int ans = 0x3f3f3f3f,cnt=0;
83 for(int i=0;i<n;i++){
84 pt[cnt++] = ln[i].a;
85 pt[cnt++] = ln[i].b;
86 }
87 pt[cnt++] = point(0,0);
88 pt[cnt++] = point(0,100);
89 pt[cnt++] = point(100,0);
90 pt[cnt++] = point(100,100);
91 sort(pt,pt+cnt,cmp);
92 for(int i=1;i<cnt;i++){
93 point cn = point((pt[i].x+pt[i-1].x)/2,(pt[i].y+pt[i-1].y)/2);
94 line lt = line(tr,cn);
95 int tot=0;
96 for(int j=0;j<n;j++){
97 if(across(lt,ln[j])) tot++;
98 }
99 if(tot<ans) ans = tot;
100 }
101 return ans+1;
102 }
103 int main()
104 {
105 while(cin>>n){
106 for(int i=0;i<n;i++){
107 cin>>ln[i].a.x>>ln[i].a.y>>ln[i].b.x>>ln[i].b.y;
108 }
109 cin>>tr.x>>tr.y;
110 int res = solve();
111 cout<<"Number of doors = "<<res<<endl;
112 }
113 return 0;
114 }