POJ 1556 计算几何+最短路

 九野的博客,转载请注明出处:http://blog.csdn.net/acmmmm/article/details/11844521

 

 代码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 1556 计算几何+最短路)