转为最短路
一截线段变成两个点,相反的方向,若换方向则需换代价
判哪些线段可以到达终点,看与顶点连线是否与其余线段又叫
真是暴力,时间复杂度(O(n^2logn))
SOL:
枚举边界上的点,到终点连线,与多少线相交即是炸的门个数
证明: 每堵墙的两个端点都在边界上,如果相交,就一定会跨过这道墙
时间复杂度(O(n^2))
n太小,直接枚举所以整点完事
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<queue>
#include<map>
#include<set>
using namespace std;
inline int read(){
int x=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f==1?x:-x;
}
struct poin{
double x,y;
poin(double xx=0,double yy=0):x(xx),y(yy){}
inline poin operator -(const poin &a)const{return poin(x-a.x,y-a.y);}
inline poin operator +(const poin &a)const{return poin(x+a.x,y+a.y);}
inline poin operator *(double a)const{return poin(x*a,y*a);}
inline poin operator /(double a)const{return poin(x/a,y/a);}
inline double operator *(const poin &a)const{return x*a.y-y*a.x;}
inline double operator /(const poin &a)const{return x*a.x+y*a.y;}
}t;
const double eps=1e-8;
struct line{
poin a,b;
line(){}
line(poin aa,poin bb):a(aa),b(bb){}
}l[32];
inline bool den(double x,double y){
return fabs(x-y)<eps;
}
inline bool inter(line x,line y){
double u=(x.a-y.a)*(x.b-y.a);
double v=u+(x.b-y.b)*(x.a-y.b);
poin tmp=(y.b-y.a)/v*u+y.a;
if(den(tmp.x,0)||den(tmp.x,100)||den(tmp.y,0)||den(tmp.y,100))return 0;
if((x.a-tmp)/(x.b-tmp)<-eps&&0<tmp.x&&tmp.x<100&&0<tmp.y&&tmp.y<100)return 1;
return 0;
}
int n,ans;
inline void solve(line r){
int ret=0;
for(int i=1;i<=n;i++)
ret+=inter(r,l[i]);
ans=min(ans,ret);
}
inline void work(){
ans=100;
for(int i=1;i<=n;i++){
l[i].a.x=read();l[i].a.y=read();
l[i].b.x=read();l[i].b.y=read();
}
scanf("%lf%lf",&t.x,&t.y);
for(int i=0;i<=100;i++){
solve(line(poin(0,i),t));
solve(line(poin(100,i),t));
}
for(int i=1;i<100;i++){
solve(line(poin(i,0),t));
solve(line(poin(i,100),t));
}
cout<<"Number of doors = "<<ans+1<<"
";
}
int main(){
while(~scanf("%d",&n))work();
return (0-0);
}