POJ 1556 计算几何+最短路

 

 

 代码1:

 

#include<iostream>

#include<stdio.h>

#include<string>

#include<string.h>

#include<algorithm>

#include<map>

#include<list>

#include<set>

#include<vector>

#include<queue>

#include<iomanip>

#include<math.h>

#define N 1050

#define ST 1001

#define EN 1002

#define M 10000

#define inf 1000000

#define eps 1e-8

#define ll long long

using namespace std;

inline ll Max(ll a,ll b){return a>b?a:b;}

inline ll Min(ll a,ll b){return a<b?a:b;}

struct Point{//点是2维的

	double x,y;

};

struct v{

	Point Start,End;

};



double Cross(Point p1,Point p2,Point p3,Point p4){//二维向量(p1p2)X(p3p4) 返回第三向量长度

	double x1=p2.x-p1.x,y1=p2.y-p1.y;

	double x2=p4.x-p3.x,y2=p4.y-p3.y;

	return x1*y2-x2*y1;	//为0表示 p1p2 与p3p4共线

	//直线:不为0就是相交

}  

double Cross_v(v v1,v v2){

	return Cross(v1.Start,v1.End,v2.Start,v2.End);

}

double point_dis(Point p1,Point p2){

	return sqrt((double)((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)));

}

bool On_Segment(Point p1,Point p2,Point p3){//p3点在 p1p2线段上

	if(Cross(p1,p2,p1,p3)!=0)return false;

	bool iny=(p1.y<=p3.y && p3.y<=p2.y)||(p1.y>=p3.y && p3.y>=p2.y);

	bool inx=(p1.x<=p3.x && p3.x<=p2.x)||(p1.x>=p3.x && p3.x>=p2.x);

	if(inx && iny)return true;

	return false;

}

bool Segmentintersect(Point p1,Point p2,Point p3,Point p4){//p1p2 是否与 p3p4相交

	double cross_1=Cross(p3,p4,p3,p1),cross_2=Cross(p3,p4,p3,p2);//cross_1 2必须一正一负且都不为0

	double cross_3=Cross(p1,p2,p1,p3),cross_4=Cross(p1,p2,p1,p4);//cross_2 4必须一正一负且都不为0

	//表示a线段 2点 在b线段 2侧

	if(cross_1*cross_2<0 && cross_3*cross_4<0)return true;



	//a线段端点在 b线段上 视情况取舍这种位置 

//	if(cross_1==0 && On_Segment(p3,p4,p1))return true;

//	if(cross_2==0 && On_Segment(p3,p4,p2))return true;

//	if(cross_3==0 && On_Segment(p1,p2,p3))return true;

//	if(cross_4==0 && On_Segment(p1,p2,p4))return true;

	return false;

}



//----------------------- 2维计算几何模版-------------------------------------

struct Edge{

	int f,t,nex;

	double w;

}edge[M];

int head[N],edgenum;

int n;

void addedge(int u,int v,double w){

	Edge E={u,v,head[u],w};

	edge[edgenum]=E;

	head[u]=edgenum++;

}



double dis[N];

void spfa(int s,int e){

	queue<int>q; 

	bool vis[N]; memset(vis,0,sizeof(vis));

	int i,u,v;

	for(i=0;i<N;i++)dis[i]=inf;

	dis[s]=0;	vis[s]=true;

	q.push(s);

	while(!q.empty()){

		u=q.front(); q.pop();

		for(i=head[u];i!=-1;i=edge[i].nex)

		{

			v=edge[i].t;

			if(dis[v]>dis[u]+edge[i].w){

				dis[v]=dis[u]+edge[i].w;

				if(!vis[v])q.push(v);

			}

		}



	}

}

Point line[N][4],Start,End;

Point Seg[N][6];

int main()

{

	int i,j;

	Start.x=0,Start.y=5;

	End.x=10,End.y=5;



	while(scanf("%d",&n),n>=0)

	{

		for(i=0;i<n;i++){

			double x,y1,y2,y3,y4;

			scanf("%lf %lf%lf %lf%lf",&x,&y1,&y2,&y3,&y4);

			line[i][0].x=line[i][1].x=line[i][2].x=line[i][3].x=x;

			line[i][0].y=y1;

			line[i][1].y=y2;

			line[i][2].y=y3;

			line[i][3].y=y4;



			Seg[i][0].x=x,Seg[i][0].y=0;

			for(j=1;j<=4;j++)Seg[i][j]=line[i][j-1];

			Seg[i][5].x=x,Seg[i][5].y=10;



		}

		memset(head,-1,sizeof(head));	edgenum=0;

		for(i=0;i<n-1;i++)

			for(j=i+1;j<n;j++)



				for(int ii=0;ii<4;ii++)

					for(int jj=0;jj<4;jj++)

					{

						bool can=true;

						for(int k=i+1;k<j && can;k++)

							for(int kk=0;kk<5 &&can;kk+=2)

								if(Segmentintersect(line[i][ii],line[j][jj],Seg[k][kk],Seg[k][kk+1]))

									can=false;



						if(can)addedge(i*10+ii,j*10+jj,point_dis(line[i][ii],line[j][jj]));

					}



					for(i=0;i<n;i++)

						for(int ii=0;ii<4;ii++)

						{

							bool cans=true,cane=true;

							for(int k=0;k<i && cans;k++)

								for(int kk=0;kk<5 &&cans;kk+=2)

									if(Segmentintersect(Start,line[i][ii],Seg[k][kk],Seg[k][kk+1]))

										cans=false;



							if(cans)addedge(ST,i*10+ii,point_dis(Start,line[i][ii]));



							for(int k=i+1;k<n && cane;k++)

								for(int kk=0;kk<5 &&cane;kk+=2)

									if(Segmentintersect(End,line[i][ii],Seg[k][kk],Seg[k][kk+1]))

										cane=false;



							if(cane)addedge(i*10+ii,EN,point_dis(End,line[i][ii]));

						}



						bool canse=true;

						for(int k=0;k<n && canse;k++)

							for(int kk=0;kk<5 &&canse;kk+=2)

								if(Segmentintersect(Start,End,Seg[k][kk],Seg[k][kk+1]))

									canse=false;

						if(canse)addedge(ST,EN,point_dis(Start,End));



						spfa(ST,EN);

						printf("%.2lf\n",dis[EN]);

	}

	return 0;

}

/*

1

5 4 6 7 8

2

4 2 7 8 9

7 3 4.5 6 7



*/








 

代码2:

#include<iostream>

#include<stdio.h>

#include<string.h>

#include<string>

#include<math.h>

#include<algorithm>

#include<stdlib.h>

#include<ctype.h>

#include<iomanip>

#include<set>

#include<map>

#include<list>

#include<vector>

#include<queue>

#include<stack>

using namespace std;

const double pi=acos(-1.0);

const double eps = 1e-8;

int sgn(double x)

{

    if(fabs(x) < eps)return 0;

    if(x < 0)return -1;

    else return 1;

}

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;

    }

    void transXY(double B)

    {

        double tx = x,ty = y;

        x = tx*cos(B) - ty*sin(B);

        y = tx*sin(B) + ty*cos(B);

    }

};

double dis(Point a,Point b)

{

        double ss=a.x-b.x;

        double tt=a.y-b.y;

        return sqrt(ss*ss+tt*tt);

}

struct Line

{

    Point s,e;

    double k;

    Line(){}

    Line(Point _s,Point _e)

    {

        s = _s;e = _e;

        k = atan2(e.y - s.y,e.x - s.x);

    }

    pair<int,Point> operator &(const Line &b)const

    {

        Point res = s;

        if(sgn((s-e)^(b.s-b.e)) == 0)

        {

            if(sgn((s-b.e)^(b.s-b.e)) == 0)

                return make_pair(0,res);

            else return make_pair(1,res);

        }

        double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));

        res.x += (e.x-s.x)*t;

        res.y += (e.y-s.y)*t;

        return make_pair(2,res);

    }

};

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-l1.s))*sgn((l1.e-l2.s)^(l2.e-l2.s)) <= 0;

}

struct NODE

{

        double x,y1,y2,y3,y4;

}pp[2000];

bool cmp(NODE a,NODE b)

{

        return a.x<b.x;

}

#define inf 10000000

const int maxn=300010;

int head[maxn],tol,m,n;

double dist[maxn];

struct Edge

{

        int to,next;

        double val;

}edge[10*maxn];

void add(int u,int v,double w)

{

        edge[tol].to=v;

        edge[tol].next=head[u];

        edge[tol].val=w;

        head[u]=tol++;

}

struct Node

{

        int id;

        double dist;

        Node(int a=0,double b=0):id(a),dist(b){}

        bool operator < (const Node &b) const

        {

                return dist>b.dist;

        }

};

void fun(int st)

{

        int i,j,u,v;

        priority_queue<Node> q;

        q.push(Node(st,0));

        for(i=1;i<=n;i++)dist[i]=inf;

        dist[st]=0;

        while(!q.empty())

        {

                Node ret=q.top();q.pop();

                u=ret.id;

                if(dist[u]<ret.dist)continue;

                for(i=head[u];i!=-1;i=edge[i].next)

                {

                        v=edge[i].to;

                        if(dist[v]>dist[u]+edge[i].val)

                        {

                                dist[v]=dist[u]+edge[i].val;

                                q.push(Node(v,dist[v]));

                        }

                }

        }

}

Line s1[500];

Point s2[500];

int main()

{

        int i,j,k,m;

        while(~scanf("%d",&m))

        {

                if(m==-1)break;

                for(i=1;i<=m;i++)scanf("%lf%lf%lf%lf%lf",&pp[i].x,&pp[i].y1,&pp[i].y2,&pp[i].y3,&pp[i].y4);

                sort(pp+1,pp+m+1,cmp);

                memset(head,-1,sizeof(head));tol=0;n=0;

                int indexx=0;

                s2[++n]=Point(0,5);

                for(i=1;i<=m;i++)

                {

                      Point p1,p2,p3,p4,p5,p6;

                      p1=Point(pp[i].x,0.0);

                      s2[++n]=p1;

                      p2=Point(pp[i].x,pp[i].y1);

                       s2[++n]=p2;

                      p3=Point(pp[i].x,pp[i].y2);

                      s2[++n]=p3;

                      p4=Point(pp[i].x,pp[i].y3);

                      s2[++n]=p4;

                      p5=Point(pp[i].x,pp[i].y4);

                      s2[++n]=p5;

                      p6=Point(pp[i].x,10.0);

                      s2[++n]=p6;

                      s1[++indexx]=Line(p1,p2);

                      s1[++indexx]=Line(p3,p4);

                      s1[++indexx]=Line(p5,p6);

                }

                s2[++n]=Point(10,5);

                for(i=1;i<=n;i++)

                {

                        for(j=i+1;j<=n;j++)

                        {

                             if(sgn(s2[i].x-s2[j].x)==0)continue;

                             Line s(s2[i],s2[j]);

                             int flag=1;

                             for(k=1;k<=indexx;k++)

                             {

                                     if(sgn(s1[k].s.x-s2[i].x)==0)continue;

                                     if(sgn(s1[k].s.x-s2[j].x)==0)continue;

                                     if(inter(s1[k],s))

                                     {

                                           flag=0;

                                           break;

                                     }

                             }

                             if(flag) add(i,j,dis(s2[i],s2[j]));

                        }

                }

                fun(1);

                printf("%.2f\n",dist[n]);

        }

        return 0;

}


 

 

你可能感兴趣的:(poj)