题目大意:求需要炸毁的墙的最少数目。
解题关键:由于是直线,所以只需要求宝藏到各个墙面中点的线段与其他线段的最少交点个数即可。再将中点转化为两个端点求小值即可。
#include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #include<cmath> #include<iostream> #define eps 1e-6 #define inf 0x3f3f3f3f using namespace std; struct Point{ double x,y; Point(){} Point(double _x,double _y){x=_x;y=_y;} Point operator-(const Point &b)const{return Point(x - b.x,y - b.y);} double operator^(const Point &b)const{return x*b.y-y*b.x;} double operator*(const Point &b)const{return x*b.x+y*b.y;} }; struct Line{ Point s,e; Line(){} Line(Point _s,Point _e){s=_s;e=_e;} }A[35]; int sgn(double x){ if(fabs(x)<eps)return 0; else if(x<0) return -1; else return 1; } //判断线段相交,模板 bool inter(Line l1,Line l2){ return max(l1.s.x,l1.e.x)>=min(l2.s.x,l2.e.x)&& max(l2.s.x,l2.e.x)>=min(l1.s.x,l1.e.x)&& max(l1.s.y,l1.e.y)>=min(l2.s.y,l2.e.y)&& max(l2.s.y,l2.e.y)>=min(l1.s.y,l1.e.y)&& sgn((l2.s-l1.s)^(l1.e-l1.s))*sgn((l2.e-l1.s)^(l1.e-l1.s))<=0&& sgn((l1.s-l2.s)^(l2.e-l2.s))*sgn((l1.e-l2.s)^(l2.e-l2.s))<=0; } int n,ans=inf; int main(){ double sx,sy; scanf("%d",&n); for(int i=0;i<n;++i) scanf("%lf%lf%lf%lf",&A[i].s.x,&A[i].s.y,&A[i].e.x,&A[i].e.y); scanf("%lf%lf",&sx,&sy); if(n==0){ ans=1; printf("Number of doors = %d ",ans); return 0; } for(int i=0;i<n;++i){ A[n].s.x=sx;A[n].s.y=sy; A[n].e.x=A[i].s.x;A[n].e.y=A[i].s.y; int cnt=0; for(int j=0;j<n;++j){ if(inter(A[j],A[n]))cnt++; } ans=min(cnt,ans); A[n].e.x=A[i].e.x;A[n].e.y=A[i].e.y; cnt=0; for(int j=0;j<n;++j){ if(inter(A[j],A[n]))cnt++; } ans=min(cnt,ans); } printf("Number of doors = %d ",ans); return 0; }