WF 2007 (UVaLive 2397) - Collecting Luggage

29 篇文章 0 订阅
15 篇文章 0 订阅

Link To The Problem


知识点: 二分,最短路,线段和多边形判交


Code:

// WF 2007 (UValive 2397 Collecting Luggage
// 知识点:二分,最短路,线段和多边形判交

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>

using namespace std;
#define FOR(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define DOR(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)

#define oo 1e6
#define eps 1e-6
#define nMax 1010

//{ 
#define pb push_back
#define dbg(x) cerr << __LINE__ << ": " << #x << " = " << x << endl

#define F first
#define S second

#define bug puts("OOOOh.....");
#define zero(x) (((x)>0?(x):-(x))<eps)

#define LL long long
#define DB double 

#define sf scanf
#define pf printf
#define rep(i,n) for(int (i)=0;(i)<(n);(i)++)

double const pi = acos(-1.0);
double const inf = 1e30;
double inline sqr(double x) { return x*x; }

int dcmp(double x){
    if(fabs(x)<eps) return 0;
    return x>0?1:-1;
}
//}

// Describe of the 2_K Geomtry
// First Part : Point and Line
// Second Part Cicle
// Third Part Polygan

// First Part:
// ****************************** Point and Line *******************************\\
//  {  

class point {
public:
    double x,y;
    point (double x=0,double y=0):x(x),y(y) {}
    void make(double _x,double _y) {x=_x;y=_y;}
    void read() { scanf("%lf%lf",&x,&y); }
    void out() { printf("%.3lf %.3lf\n",x,y);}
    double len() { return sqrt(x*x+y*y); }

    point friend operator - (point const& u,point const& v) { return point(u.x-v.x,u.y-v.y); }
    point friend operator + (point const& u,point const& v) { return point(u.x+v.x,u.y+v.y); }
    double friend operator * (point const& u,point const& v){ return u.x*v.y-u.y*v.x; }
    double friend operator ^ (point const& u,point const& v) { return u.x*v.x+u.y*v.y; }
    point friend operator * (point const& u,double const& k) { return point(u.x*k,u.y*k); }
	point friend operator / (point const& u,double const& k) { return point(u.x/k,u.y/k); }
	
	friend bool operator < (point const& u,point const& v){
		if(dcmp(v.x-u.x)==0) return dcmp(u.y-v.y)<0;
		return dcmp(u.x-v.x)<0;
	}
	friend bool operator != (point const& u,point const& v){
		return dcmp(u.x-v.x) || dcmp(u.y-v.y);
	}

	point rotate(double s) {
		return point(x*cos(s) + y*sin(s),\
					-x*sin(s) + y*cos(s));
	}
};
typedef point Vector;
typedef class line{
public:
    point a,b;
    line() {}
    line (point a,point b):a(a),b(b){}
    void make(point u,point v) {a=u;b=v;}
    void read() { a.read(),b.read(); }
}segment;

double det(point u,point v) {
	return u.x*v.y - u.y*v.x;
}
double dot(point u,point v) {
	return u.x*v.x + u.y*v.y;
}

// Weather P is On the Segment (uv) 
int dot_on_seg(point p,point u,point v){
	return dcmp(det(p-u,v-p))==0 && dcmp(dot(p-u,p-v)) <= 0; // '>=' means P is u or v
}
// The distance from point p to line l
double PToLine(point p,line l) {
	return fabs((p-l.a)*(l.a-l.b))/(l.a-l.b).len();
}
// The ProJect Of Point(p) To Line(l)
point PointProjectLine(point p,line l) {
	double t = dot(l.b-l.a,p-l.a)/dot(l.b-l.a,l.b-l.a);
	return l.a + (l.b-l.a)*t;
}
// Weather line u parallel line v
int parallel(line u,line v) {
	return dcmp(det(u.a-u.b,v.a-v.b))==0;
}
// The Intersection Point Of Line u and Line v
point intersection(line u,line v) {
	point ret = u.a;
	double t = det(u.a-v.a,v.a-v.b)/det(u.a-u.b,v.a-v.b);
	return ret + (u.b-u.a)*t;
}

//}
// ****************************** First Part end ********************************\\

// Second Part:
// ********************************* Circle *************************************\\
// {

struct circle {
	point O;
	double r;
	circle() {};
	circle(point O,double r):O(O),r(r){};
};

//}
// ****************************** Second Part End *******************************\\

// Third Part :
// ********************************* Polygan *************************************\\
// {


int ConvexHull(vector<point>& p){
	int n=p.size();
	int m=0;
	vector<point> q;
	q.resize(2*n+5);
	rep(i,n) {
		while(m>1 && dcmp((q[m-1]-q[m-2])*(p[i]-q[m-2])) <= 0) m--;
		q[m++] = p[i];
	}
	int k = m;
	for(int i=n-2;i>=0;i--) {
		while(m>k && dcmp((q[m-1]-q[m-2])*(p[i]-q[m-2])) <= 0) m--;
		q[m++] = p[i];
	}
	q.resize(m) ;
	if(m>1) q.resize(m-1);
	// p = q;    // 是否修改原来的多边形
	return q.size();
}
// 三角形重心
point Center(point a,point b,point c){
	return (a+b+c)/3.0;
}
// Centroid of Polygan
point Centroid(vector<point> p){
	point O(0,0),ret(0,0);
	int n = p.size();
	p.pb(p[0]);
	double area = 0.0;
	rep(i,n) {
		ret = ret + Center(O,p[i],p[i+1])*dot(p[i]-O,p[i+1]-O);
		area += dot(p[i]-O,p[i+1]-O);
	}
	if(dcmp(area)==0) {
		pf("There maybe something wrong\n");
		return p[0];
	}
	return ret / area;
}


struct Polygan{
	vector<point> g;
	Polygan() {};
	Polygan(vector<point> g):g(g){};
	Polygan(point p[],int n) {g.clear();rep(i,n) g.pb(p[i]); };
	int convex() { return ConvexHull(g); }
	point center() { return Centroid(g);  } // 多边形的重心
};

//}
// ******************************* Third Part End ********************************\\






int n;
double g[nMax][nMax],h[nMax];
int vis[nMax];
queue<int> que;
double MinDist(int t,int s) {
	while(!que.empty()) que.pop();
	rep(i,n+2) vis[i]=0,h[i]=inf;
	h[s]=0;vis[s]=1;que.push(s);
	int u,v;
	while(!que.empty()){
		u=que.front();que.pop();
		rep(i,n+1) if(dcmp(g[i][u]-inf)<0) {
			if(dcmp(h[i]-h[u]-g[i][u])>0) {
				h[i]=h[u]+g[u][i];
				if(!vis[i]){
					vis[i]=1;
					que.push(i);
				}
			}
		}
		vis[u]=0;
	}
	return h[t];
}

point p[nMax],s;
double vs,vp;
segment l[nMax];
double T,t[nMax],d[nMax];


int dot_on_seg_ex(point p,point u,point v){
	return dcmp(det(p-u,v-p))==0 && dcmp(dot(p-u,v-p)) > 0; // '>=' means P is u or v
}
int LLJ(line l,point u,point v,point& tmp){
	if(parallel(l,line(u,v))) {
		if(dot_on_seg(l.a,u,v)) { tmp = l.a ; return -1;}
		if(dot_on_seg(l.b,u,v)) { tmp = l.b ; return -1;}
		if(dot_on_seg(u,l.a,l.b)) { tmp = u ; return -1;}
		if(dot_on_seg(v,l.a,l.b)) { tmp = v ; return -1;} 
		return 0;
	}
	tmp = intersection(l,line(u,v));
	if(dot_on_seg_ex(tmp,l.a,l.b) && dot_on_seg_ex(tmp,u,v)) return 1;
	if(dot_on_seg(tmp,l.a,l.b) && dot_on_seg(tmp,u,v)) return -1;
	return 0;
}
int Point_In(point t) {
	int num=0,i,d1,d2,k;
	p[n]=p[0];
	for(i=0;i<n;i++) {
		if(dot_on_seg(t,p[i],p[i+1])) return 0;
		k = dcmp(det(p[i+1]-p[i],t-p[i]));
		d1 = dcmp(p[i].y-t.y);
		d2 = dcmp(p[i+1].y-t.y);
		if(k>0 && d1<=0 && d2>0) num++;
		if(k<0 && d2<=0 && d1>0) num--;
	}
	return num!=0;
}
int chk(point a,point b){
	point tmp;
	vector<point> res;
	res.clear();
	res.pb(a),res.pb(b);
	int d;
	rep(i,n) {
		d = LLJ(l[i],a,b,tmp);
		if(d==1) return 0;
		else if(d==-1) {
			res.pb(tmp);
		}
	}
	sort(res.begin(),res.end());
	rep(i,res.size()-1){
		if(Point_In((res[i]+res[i+1])/2.0)) return 0;
	}
	return 1;
}

/*double inline fmod(double x,double mo){
	int b = (int)(x/mo);
	x -= b*mo;
	return x;
}*/

point find(double cur){
	cur *= vp;
	cur = fmod(cur,T);
	int i=0;
	while(cur >= d[i]) {cur-=d[i];i++;}
	point n = l[i].b-l[i].a;
	n = n/n.len();

	return n*cur + l[i].a;
}

int deal(double cur) {
	point q = find(cur);
	rep(i,n) if(chk(q,p[i])) g[i][n+1]=g[n+1][i]=(q-p[i]).len();
	else g[i][n+1]=g[n+1][i]=inf;
	if(chk(q,s)) g[n][n+1]=g[n+1][n]=(s-q).len();
	else g[n][n+1]=g[n+1][n]=inf;
	double ret = MinDist(n,n+1);
	return dcmp(ret-cur*vs) <= 0;
}

int cas = 1;
void work() {
	p[n]=p[0];
	rep(i,n) l[i]=line(p[i],p[i+1]);
	rep(i,n) d[i]=(l[i].a-l[i].b).len();
	T=0;
	rep(i,n) T += d[i];

	rep(i,n) for(int j=i+1;j<n;j++) if(i!=j) {
		if(chk(p[i],p[j])) {
			g[i][j]=g[j][i]=(p[i]-p[j]).len();
		}else g[i][j]=g[j][i]=inf;
	}
	rep(i,n) if(chk(s,p[i])) g[i][n]=g[n][i]=(s-p[i]).len();
	else g[i][n]=g[n][i]=inf;
	//rep(i,n+1) { rep(j,n+1) pf("%.3lf ",g[i][j]);pf("\n");}

	double la=0,ra=1e8;
	double ans,mid;
	while(ra-la > 1e-8){
		mid = (la+ra)/2.0;
		if(deal(mid)) ra=mid;
		else la=mid;
	}

	int Base = ((la+ra)*30+0.5+eps);
	pf("Case %d: Time = %d:%02d\n",cas++,Base/60,Base%60);
}
int main() {
#ifndef ONLINE_JUDGE
	freopen("in.txt","r",stdin);
	freopen("out.txt","w",stdout);
#endif

	while(~sf("%d",&n) , n){
		rep(i,n) p[i].read();
		s.read();
		sf("%lf%lf",&vp,&vs);
		work();
	}

	return 0;
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值