有个地方要转化一下:
只能从中点炸开这个条件,实际上等价于从起点出发到终点要经过多少堵墙
因为所有墙都是直线,所以一旦在路上堵着永远绕不开,反正不在路上的墙不管从哪里进入都不会被碰到
所以不用枚举中点,直接枚举边上的端点,和终点连线,判严格相交即可
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; #define db double #define N 200 const db eps=1e-6; int sign(db k){if (k>eps) return 1; else if (k<-eps) return -1; return 0;} int cmp(db k1,db k2){return sign(k1-k2);} struct point { db x,y; point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};} point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};} point operator * (db k1) const{return (point){x*k1,y*k1};} point operator / (db k1) const{return (point){x/k1,y/k1};} }; struct line{ point p[2]; }; db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;} int intersect(db l1,db r1,db l2,db r2){ if (l1>r1) swap(l1,r1); if (l2>r2) swap(l2,r2); return cmp(r1,l2)!=-1&&cmp(r2,l1)!=-1; } int checkSS(point k1,point k2,point k3,point k4){ int res3=sign(cross(k3-k1,k4-k1)); int res4=sign(cross(k3-k2,k4-k2)); return res3*res4<0&& sign(cross(k1-k3,k2-k3))*sign(cross(k1-k4,k2-k4))<0; } point p[N]; line l[N]; int n,totp; point T; int main(){ cin>>n; totp++;p[totp].x=p[totp].y=0; totp++;p[totp].x=p[totp].y=100; totp++;p[totp].x=100;p[totp].y=0; totp++;p[totp].x=0;p[totp].y=100; for(int i=1;i<=n;i++){ point k1,k2; scanf("%lf%lf",&k1.x,&k1.y); scanf("%lf%lf",&k2.x,&k2.y); p[++totp]=k1;p[++totp]=k2; l[i].p[0]=k1;l[i].p[1]=k2; } scanf("%lf%lf",&T.x,&T.y); int Min=0x3f3f3f3f; for(int i=1;i<=totp;i++){//枚举每个端点作为起点 int tot=0; for(int j=1;j<=n;j++){if(checkSS(p[i],T,l[j].p[0],l[j].p[1]))tot++;} Min=min(Min,tot); } cout<<"Number of doors = "<<Min+1<<' '; }