http://poj.org/problem?id=1066
在下图中,
求解从四边到中间终点至少要穿过几堵墙。
浮点数据的线段判断是否相交。另外,我们需要设置四边的起点,不是直接遍历每个坐标,而是找已有的交点。(有一种贪心的意思)。
#include <iostream> #include <cstdio> #include <cmath> using namespace std; const double eps=1e-6; struct point { double x,y; }; struct edge{ point u,v; }eg[40]; double min(double q1,double q2){ return q1-q2<eps?q1:q2; } double max(double q1,double q2){ return q1-q2>eps?q1:q2; } bool on(point a,point b,point c){ if(c.x>=min(a.x,b.x)&&c.x<=max(a.x,b.x)&&c.y>=min(a.y,b.y)&&c.y<=max(a.y,b.y)) return 1; return 0; } double multi(point p0,point p1,point p2){ return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); } bool cross(point p1,point p2,point p3,point p4){ bool tag=0; double r1=multi(p3,p4,p1),r2=multi(p3,p4,p2); double r3=multi(p1,p2,p3),r4=multi(p1,p2,p4); if(r1*r2<eps&&r3*r4<eps) tag=1; else if(fabs(r1)<eps&&on(p3,p4,p1))tag=1; else if(fabs(r2)<eps&&on(p3,p4,p2))tag=1; else if(fabs(r3)<eps&&on(p1,p2,p3))tag=1; else if(fabs(r4)<eps&&on(p1,p2,p4)) tag=1; return tag; } int main() { //freopen("cin.txt","r",stdin); int n; while(cin>>n){ point u,v; for(int i=0;i<n;i++) { scanf("%lf%lf%lf%lf",&eg[i].u.x,&eg[i].u.y,&eg[i].v.x,&eg[i].v.y); } scanf("%lf%lf",&eg[n].u.x,&eg[n].u.y); if(n==0){ puts("Number of doors = 1"); continue; } int ans=n; for(int i=0;i<n;i++){ //就选择交点作为另一个端点 eg[n].v.x=eg[i].u.x; eg[n].v.y=eg[i].u.y; int sum=0; for(int j=0;j<n;j++){ if(cross(eg[n].u,eg[n].v,eg[j].u,eg[j].v)) sum++; } ans=ans<sum?ans:sum; eg[n].v.x=eg[i].v.x; eg[n].v.y=eg[i].v.y; sum=0; for(int j=0;j<n;j++){ if(cross(eg[n].u,eg[n].v,eg[j].u,eg[j].v)) sum++; } ans=ans<sum?ans:sum; } printf("Number of doors = %d\n",ans); } return 0; }
#include <iostream> #include <cstdio> #include <cmath> using namespace std; const double eps=1e-6; struct point { double x,y; }; struct edge{ point u,v; }eg[40]; double multi(point p0,point p1,point p2){ return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y); } bool cross(point p1,point p2,point p3,point p4){ bool tag=0; double r1=multi(p3,p4,p1),r2=multi(p3,p4,p2); double r3=multi(p1,p2,p3),r4=multi(p1,p2,p4); if(r1*r2<eps&&r3*r4<eps) tag=1; //如果是端点接触相交 r1*r2趋近于0 tag=1 return tag; } int main() { //freopen("cin.txt","r",stdin); int n; while(cin>>n){ point u,v; for(int i=0;i<n;i++) { scanf("%lf%lf%lf%lf",&eg[i].u.x,&eg[i].u.y,&eg[i].v.x,&eg[i].v.y); } scanf("%lf%lf",&eg[n].u.x,&eg[n].u.y); if(n==0){ puts("Number of doors = 1"); continue; } int ans=n; for(int i=0;i<n;i++){ //就选择交点作为另一个端点 eg[n].v.x=eg[i].u.x; eg[n].v.y=eg[i].u.y; int sum=0; for(int j=0;j<n;j++){ if(cross(eg[n].u,eg[n].v,eg[j].u,eg[j].v)) sum++; } ans=ans<sum?ans:sum; eg[n].v.x=eg[i].v.x; eg[n].v.y=eg[i].v.y; sum=0; for(int j=0;j<n;j++){ if(cross(eg[n].u,eg[n].v,eg[j].u,eg[j].v)) sum++; } ans=ans<sum?ans:sum; } printf("Number of doors = %d\n",ans); } return 0; }