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
这道题的大概意思是一个100*100的正方形,给你n条边,然后接下来的n行的4数,分别是这条边的两端点坐标,最后给你一个浮点型坐标,即终点,问你从正方形外面到达终点最少需要穿过几条边的中点。
思路,因为我们每穿过一条边,都必须要从其中点穿过,所以这个问题可等价于终点与正方形每条边上由线段端点形成的小边的中点的连线最少与多少条边相交的问题。当有0条边时,我们只用穿过正方形的一条边的中点即可,当边不为0时,我们判断其小边中点与中点的连线最少与多少条正方形内的线段相交,再加上1,就是正确答案(因为从正方形的某一条边进去)。所以,此题枚举正方形上四条边上的小边中点与终点的连线,再算出与正方形内线段的最少交点即可。
如何判断两条线段相交,设有线段AB与CD,线段AB与CD相交的充要条件是端点C和D在直线AB两端或在其上且端点A和B在直线CD两端或在其上。
代码如下:
#include <algorithm>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
using namespace std;
struct note
{
double x1;
double y1;
double x2;
double y2;
};
struct note a[35];
//四个数组分别存正方形四条边上的点的x或y坐标
double kk1[35];
double kk2[35];
double kk3[35];
double kk4[35];
//判断线段相交
double chacheng(double x1,double y1,double x2,double y2,note b)
{
if(((x2-x1)*(b.y1-y1)-(b.x1-x1)*(y2-y1))*((x2-x1)*(b.y2-y1)-(b.x2-x1)*(y2-y1))<=0&&((b.x2-b.x1)*(y1-b.y1)-(x1-b.x1)*(b.y2-b.y1))*((b.x2-b.x1)*(y2-b.y1)-(x2-b.x1)*(b.y2-b.y1))<=0)
return 1;
else
return 0;
}
int main()
{
freopen("in.txt","r",stdin);
int T;
while(scanf("%d",&T)!=EOF)
{
int k1=1;
int k2=1;
int k3=1;
int k4=1;
//起始坐标
kk1[0]=0;
kk2[0]=0;
kk3[0]=0;
kk4[0]=0;
for(int i=0;i<T;i++)
{
scanf("%lf %lf %lf %lf",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2);
//将端点1存入所在正方形边所对应的数组中
if(a[i].x1==0)
{
kk1[k1]=a[i].y1;
k1++;
}
else if(a[i].x1==100)
{
kk2[k2]=a[i].y1;
k2++;
}
else if(a[i].y1==100)
{
kk3[k3]=a[i].x1;
k3++;
}
else
{
kk4[k4]=a[i].x1;
k4++;
}
//将端点2存入所在正方形边所对应的数组中
if(a[i].x2==0)
{
kk1[k1]=a[i].y2;
k1++;
}
else if(a[i].x2==100)
{
kk2[k2]=a[i].y2;
k2++;
}
else if(a[i].y2==100)
{
kk3[k3]=a[i].x2;
k3++;
}
else
{
kk4[k4]=a[i].x2;
k4++;
}
}
double x,y;
scanf("%lf %lf",&x,&y);
//对正方形内没有线段的情况特判
if(T==0)
{
printf("Number of doors = 1\n");
continue;
}
//最终坐标
kk1[k1]=100;
kk2[k2]=100;
kk3[k3]=100;
kk4[k4]=100;
//将正方形四条边上的点进行排序
sort(kk1,kk1+k1);
sort(kk2,kk2+k2);
sort(kk3,kk3+k3);
sort(kk4,kk4+k4);
//求四条边上各个小边的中点,存在数组中
for(int i=0;i<k1;i++)
kk1[i]=(kk1[i]+kk1[i+1])/2;
for(int i=0;i<k2;i++)
kk2[i]=(kk2[i]+kk2[i+1])/2;
for(int i=0;i<k3;i++)
kk3[i]=(kk3[i]+kk3[i+1])/2;
for(int i=0;i<k4;i++)
kk4[i]=(kk4[i]+kk4[i+1])/2;
//分别枚举正方形四条边上的各小边的中点与终点的连线,并求出与正方形内部线段相交最少的数目
int Min=100;
int jishu=0;
for(int i=0;i<k1;i++)
{
int jishu=0;
for(int j=0;j<T;j++)
if(chacheng(0,kk1[i],x,y,a[j]))
jishu++;
if(jishu<Min)
Min=jishu;
}
for(int i=0;i<k2;i++)
{
int jishu=0;
for(int j=0;j<T;j++)
if(chacheng(100,kk2[i],x,y,a[j]))
jishu++;
if(jishu<Min)
Min=jishu;
}
for(int i=0;i<k3;i++)
{
int jishu=0;
for(int j=0;j<T;j++)
if(chacheng(kk3[i],100,x,y,a[j]))
jishu++;
if(jishu<Min)
Min=jishu;
}
for(int i=0;i<k4;i++)
{
int jishu=0;
for(int j=0;j<T;j++)
if(chacheng(kk4[i],0,x,y,a[j]))
jishu++;
if(jishu<Min)
Min=jishu;
}
//因为从正方形外进入,要穿过正方形的一条边,故加1
printf("Number of doors = %d\n",Min+1);
}
return 0;
}