poj 1556 The Doors

        题意:有一个10*10的矩形,你在(0,5),要走到(10,5),中间有一些障碍阻挡,障碍都是平行于y轴的,中间有两个区间是“门”,可以通过,求最短路径。

        思路:先建图,最短路径肯定是贴着门边的,如果两个顶点(门边)之间没有线段阻挡,连接这两个顶点。然后根据建好的图求最短路。这个题我做了三天。。。因为中间有个很2的逻辑错误一直没有发现。


#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <ctype.h>

using namespace std;




double wall[20][4];
double wallx[20];
double a[80];

struct point{
	double x;
	double y;
	point(double xx,double yy){
		x=xx;
		y=yy;
	}
};


bool cp(double xa,double ya,double xb,double yb){//向量叉积
	return (xa*yb-xb*ya)<0;
}

bool judge(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4){//线段判交
	//printf("检测(%lf,%lf),(%lf,%lf)和(%lf,%lf),(%lf,%lf)的相交情况.\n",x1,y1,x2,y2,x3,y3,x4,y4);
	bool re=(cp(x2-x1,y2-y1,x3-x1,y3-y1)!=cp(x2-x1,y2-y1,x4-x1,y4-y1))&&(cp(x4-x3,y4-y3,x1-x3,y1-y3)!=cp(x4-x3,y4-y3,x2-x3,y2-y3));
	return re; 
}

double dist(double x1,double y1,double x2,double y2){//两点间距离
	return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}

struct edge{
	int next;
	double weight;
	edge(int n,double w){
		next=n;
		weight=w;
	}
};


int main(){
	int n;
	while(~scanf("%d",&n)){
		if(n==-1)break;
		vector<edge> v[80];
		//输入 
		for(int i=1;i<=n;i++){
			scanf("%lf",&wallx[i]);
			for(int j=0;j<4;j++){
				scanf("%lf",&wall[i][j]);
			}
		}
		wallx[0]=0.0;
		wall[0][0]=wall[0][1]=wall[0][2]=wall[0][3]=5.0;
		wallx[n+1]=10.0;
		wall[n+1][0]=wall[n+1][1]=wall[n+1][2]=wall[n+1][3]=5.0;
		//建图 
		
		
		queue<int> que;
		que.push(0);
		
		while(!que.empty()){
			int cur=que.front();
			que.pop();
			int curx,cury;
			
			if(cur==0){
				curx=0;
				cury=0;
			}else{
				curx=(cur-1)/4+1;
				cury=(cur-1)%4;
			}
			if(!v[cur].empty())continue;
			for(int i=curx+1;i<=n+1;i++){//n个墙壁 
			
				for(int k=0;k<4;k++){//4个顶点 
					
					bool flag=true;
					for(int j=curx+1;j<i;j++){//扫描之前的墙壁 
						if( judge(wallx[curx],wall[curx][cury],wallx[i],wall[i][k],  wallx[j],0.0,wallx[j],wall[j][0])){
							flag=false;
							break;
						}
						if( judge(wallx[curx],wall[curx][cury],wallx[i],wall[i][k],  wallx[j],wall[j][1],wallx[j],wall[j][2])){
							flag=false;
							break;
						}
						if( judge(wallx[curx],wall[curx][cury],wallx[i],wall[i][k],  wallx[j],wall[j][3],wallx[j],10.0)){
							flag=false;
							break;
						}
					}
					if(flag){//没有阻碍,可以连接 
						edge n((i-1)*4+k+1,dist(wallx[curx],wall[curx][cury],wallx[i],wall[i][k]));
						v[cur].push_back(n);
						que.push((i-1)*4+k+1);
						//printf("连接(%lf,%lf)和(%lf,%lf)!\n",wallx[curx],wall[curx][cury],wallx[i],wall[i][k]); 
					}else{
						//printf("连接失败.\n");
					}
					if(i==(n+1))break;
				}
			} 
		}
		
		for(int i=0;i<80;i++){
			a[i]=9999.9;
		}
		a[0]=0.0;
		
		queue<int> que2;
		que2.push(0);
		
		while(!que2.empty()){
			int cur=que2.front();
			que2.pop();
			for(int i=0;i<v[cur].size();i++){
				if( (v[cur][i].weight+a[cur])<a[v[cur][i].next] ){
					a[v[cur][i].next]=(v[cur][i].weight+a[cur]);
					que2.push(v[cur][i].next);
				}
			}
		}
		
//		for(int i=0;i<=n*4+1;i++){
//			cout<<a[i]<<endl;
//		}
		printf("%.2lf\n",a[n*4+1]);
	}
	
	return 0;
}




你可能感兴趣的:(poj,图论,计算几何)