【题目来源】:https://vjudge.net/problem/POJ-1066
【题意】
给出一个100*100的矩形,中间有好多条线段分割成一个个独立的空间,然后给出宝藏的坐标,因为要拿到宝藏,所以,要炸掉一部分线段,并且,规定只能炸掉线段中点,问,最少炸掉几条线段才能够拿到宝藏?
【思路】
就像题面表示的那幅图,炸掉了一堵墙,以及一条线段,问题可以表述为从内部定点,到四周墙上的最少穿过的线段数量,然后,就想到了线段相交,遍历墙上所有点,判断从定点到该点与几条线段相交,但是两线段可能共端点,那么这个时候就不是相交了,所以数量不会增加。
特判:当n==0的时候,输出1,因为还有一堵墙,但是,重点中的重点,输入n之后,他还要输入一个点的坐标。。。。(已经冥思苦想了好久。。)
【代码】
#include<cmath>
#include<cstdio>
#include<list>
#include<cstring>
#include<algorithm>
#define INF 1e9
using namespace std;
typedef long long LL;
const double esp=1e-6;
struct point
{
double x,y;
}a[100];
int n;
bool quick_check(point s,point t,point ss,point tt)//快速排斥实验
{
if(min(s.x,t.x)<=max(ss.x,tt.x)&&min(s.y,t.y)<=max(ss.y,tt.y)&&min(ss.x,tt.x)<=max(s.x,t.x)&&min(ss.y,tt.y)<=max(s.y,t.y))
return 1;
else return 0;
}
double cross(point s,point t,point w)//叉乘
{
return (s.x-t.x)*(w.y-t.y)-(w.x-t.x)*(s.y-t.y);
}
bool kua_li(point s,point t,point ss,point tt)//跨立实验
{
if(!quick_check(s,t,ss,tt)) return false;
if(cross(s,t,ss)*cross(s,t,tt)>=-esp) return false;//除去共端点的情况,所以是>=-esp
if(cross(ss,tt,s)*cross(ss,tt,t)>=-esp) return false;
return true;
}
int main()
{
while(~scanf("%d",&n))
{
int tot=0;
for(int i=0;i<n;i++)
{
scanf("%lf%lf",&a[tot++].x,&a[tot].y);
scanf("%lf%lf",&a[tot++].x,&a[tot].y);
}
scanf("%lf%lf",&a[tot].x,&a[tot].y);
if(n==0)
{
printf("Number of doors = 1\n");
continue;
}
int minn=INF;
for(int i=0;i<2*n;i++)
{
int num=0;
for(int j=0;j<n;j++)
{
if(kua_li(a[i],a[tot],a[j*2],a[j*2+1]))
{
num++;
}
}
if(num<minn)
minn=num;
}
printf("Number of doors = %d\n",minn+1);
}
}