呵呵。。。




 記錄一下端點間直接路徑,然後跑最短路

#include <cstdio>  
#include <cmath>  
#include <ctime>  
#include <string>  
#include <cstring>  
#include <cstdlib>  
#include <iostream>  
#include <algorithm>  
  
#include <set> 
#include <stack>  
#include <queue>  
#include <vector>  
 
#define pb push_back 
#define lb lower_bound 
#define sqr(x) (x)*(x) 
#define lowbit(x) (x)&(-x)  
#define Abs(x) ((x) > 0 ? (x) : (-(x)))  
#define FOR(i,a,b) for((i)=(a);(i)<=(b);(i)++)  
#define FORP(i,a,b) for(int i=(a);i<=(b);i++)  
#define FORM(i,a,b) for(int i=(a);i>=(b);i--)  

#define maxn 1005 
#define maxm 100005 
#define INF 1070000000  
using namespace std;  
typedef long long ll;  
typedef unsigned long long ull;  
  
template<class T> inline  
void read(T& num){  
    num = 0; bool f = true;char ch = getchar();  
    while(ch < '0' || ch > '9') { if(ch == '-') f = false;ch = getchar();}  
    while(ch >= '0' && ch <= '9') {num = num * 10 + ch - '0';ch = getchar();}  
    num = f ? num: -num;  
} 
int out[100]; 
template<class T> inline 
void write(T x,char ch){ 
	if (x==0) {putchar('0'); putchar(ch); return;} 
	if (x<0) {putchar('-'); x=-x;} 
	int num=0; 
	while (x){ out[num++]=(x%10); x=x/10;} 
	FORM(i,num-1,0) putchar(out[i]+'0'); putchar(ch); 
} 
/*==================split line==================*/ 
const double eps=1e-8; 
int n, cnt, cntl;
double dis[maxn][maxn];
int T;

struct Vec{
	double x,y;
	Vec(){}
	Vec(double _x,double _y) :x(_x),y(_y){}
	bool operator == (const Vec &k) const{
		return (fabs(x - k.x) <= eps) && (fabs(y - k.y) <= eps);
	}
};
typedef Vec Poi;
Poi p[maxn];
struct Line{
	Poi s,t;
	Line(){}
	double getdis(){ return sqrt(sqr(s.x - t.x) + sqr(s.y - t.y)); }
}line[maxn];
bool eq(double x,double y){return fabs(x-y)<=eps;}
inline double cross(Poi a,Poi b){return a.x * b.y - a.y * b.x;}
inline Poi operator - (Poi a, Poi b) {return Poi(a.x - b.x, a.y - b.y); }

inline double turn(Poi a,Poi b,Poi c){return cross(b-a,c-a);}

bool judge(Poi a,Poi b){
	FORP(i, 1, cntl) {
		if (a == line[i].s && b == line[i].t) return true;
		if (turn(a,b,line[i].s) * turn(a,b,line[i].t) <  - eps && 
			turn(line[i].s, line[i].t, a) * turn(line[i].s, line[i].t, b) < -eps) return false;	
	}	
	return true;
}
bool seeable(Poi a, Poi b, int x, int y){
	if (x % 2 == 0) x--; if (y % 2 == 1) y++;
	double k = (b.y - a.y) / (b.x - a.x);
	for (int i = x; i <= y; i += 2){
		double pos = (p[i].x - a.x) * k + a.y;
		if (pos < p[i].y || pos > p[i + 1].y) return false;
	}
	return true;
}
double w; 
double xx[maxn], yy[maxn];
void init(){
	read(n); n++;
	FORP(i, 0, maxn)
		FORP(j, 0, maxn) dis[i][j] = INF;
	FORP(i, 1, n) scanf("%lf%lf",&xx[i],&yy[i]);
	scanf("%lf",&w);
	FORP(i, 1, n){
		double x = xx[i], y = yy[i];
		p[++cnt] = Poi(x, y), p[++cnt] = Poi(x, y + w);
		if (i > 1){
			line[++cntl].s = p[cnt - 3], line[cntl].t = p[cnt - 1];
			dis[cnt - 3][cnt - 1] = dis[cnt - 1][cnt - 3] = line[cntl].getdis();
			line[++cntl].s = p[cnt - 2], line[cntl].t = p[cnt];
			dis[cnt][cnt - 2] = dis[cnt - 2][cnt] = line[cntl].getdis();
		}
	}
	
}
struct HeapNode{
	double d;
	int u;
	bool operator <(const HeapNode& rhs) const{
		return d > rhs.d;
	}
};
bool done[maxn];
double dist[maxn];
priority_queue<HeapNode> q;
void dijkstra(){
	FORP(i, 0, T) dist[i] = INF;
	dist[0] = 0; q.push((HeapNode){0,0});
	while (!q.empty()){
		HeapNode x = q.top(); q.pop();
		int u = x.u;
		if (done[u]) continue;
		done[u] = true;
		FORP(i, 0, T) if (dist[i] > dist[u] + dis[u][i]){
			dist[i] = dist[u] + dis[u][i];
			q.push((HeapNode){dist[i], i});
		}
	}
}
void work(){
	T = cnt + 1;
	double up = p[2].y,down = p[1].y; bool flag = true;
	for (int i = 3; i <= cnt; i+= 2){
		if (p[i].y > up) {flag = false; break;}
		if (p[i + 1].y < down) {flag = false; break;}
		if (p[i + 1].y < up) dis[0][i + 1] = dis[i + 1][0] = p[i + 1].x;
		if (p[i].y > down) dis[0][i] = dis[i][0] = p[i].x;
		up = min(up, p[i + 1].y); down = max(down, p[i].y);
	}
	if (flag) {printf("%lf\n", p[cnt].x - p[1].x); return;}
	up = p[cnt].y, down = p[cnt - 1].y; flag = true;
	for (int i = cnt - 2; i >= 1; i -= 2){
		if (p[i - 1].y > up) {flag = false; break;}
		if (p[i].y < down) {flag = false; break;}
		if (p[i].y < up) dis[T][i] = dis[i][T] = p[cnt].x - p[i].x;
		if (p[i - 1].y > down) dis[T][i - 1] = dis[i - 1][T] = p[cnt].x - p[i - 1].x;
		up = min(up, p[i].y); down = max(down, p[i - 1].y);
	}
	FORP(i, 1, cnt)
		FORP(j, i + 1, cnt) 
			if (p[i].x != p[j].x){
				Line temp; temp.s = p[i]; temp.t = p[j];
				if (seeable(p[i], p[j], i, j) && judge(p[i], p[j])) {
					double len = temp.getdis();
					dis[i][j] = dis[j][i] = temp.getdis();
				}
			}
	dis[0][1] = dis[1][0] = dis[0][2] = dis[2][0] = 
	dis[T][cnt] = dis[cnt][T] = dis[T][cnt - 1] = dis[cnt - 1][T] = 0;
	dijkstra();
	printf("%.10lf\n",dist[T]);
}
int main(){
	init();
	work();
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章