HDU 5027 Help!

3 篇文章 0 订阅
这是一篇关于HDU 5027问题的博客,作者探讨了题目中的分类讨论和解决方案。文章提到C++读入速度的问题,指出在计算几何问题中不应过分关注时间效率,并对网上使用圆与线段交的方法表示疑惑。文中还附带了一段相关的代码。
摘要由CSDN通过智能技术生成

三分趣题, 分类讨论.

之前C++读入被各种卡时间= = 真是坑, G++就过了

计算几何什么的就别卡时间啦...

P.S. 为何网上有人用圆与线段交(疑惑)?

附上奇怪的代码


#include<iostream>
#include<cstdio>
#include<complex>
#include<vector>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
const double eps=1.0e-8;
typedef complex<double> point;
typedef vector<point> polygon;
struct line : public vector<point> {
    line() {}
    line(const point& a, const point& b) { push_back(a); push_back(b); }
};
inline point vec(const line& l) { return l[1]-l[0];}
inline double dot  (const point& a, const point& b) { return (a*conj(b)).real();}
inline double cross(const point& a, const point& b) { return (conj(a)*b).imag();}
inline int dlcmp(const double& x){
    return x<-eps?-1:x>eps;
}
bool intersectSP(const line& s, const point& p) {
    return abs(s[0]-p)+abs(s[1]-p)<abs(s[1]-s[0])+eps;
}
point projection(const line &l, const point &p) {
    double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
    return l[0] + t*(l[0]-l[1]);
}
double distanceSP(const line &s, const point &p) {
    const point& r = projection(s, p);
    if (intersectSP(s, r)) return abs(r - p);
    return min(abs(s[0]-p), abs(s[1]-p));
}
polygon p;
const int MAXN=50005;
bool direction[MAXN];
inline double calc(const point& start, const point& m, const point& target, const double& Vr, const double& Vs){
    return abs(start-m)/Vr+abs(m-target)/Vs;
}
point m1, m2, v;
double mid, midd;
double solve(const line& S, const point& start, const point& target, const double& Vr, const double& Vs, double& ts){
    double l=0.0, r=1.0;
    v=vec(S);
    while(l+eps<r){
        mid=(l+r)/2.0;
        midd=(mid+r)/2.0;
        m1=S[0]+mid*v;
        m2=S[0]+midd*v;
        if(calc(start,m1,target,Vr,Vs)<calc(start,m2,target,Vr,Vs)){
            r=midd;
        }
        else{
            l=mid;
        }
    }
    ts=abs(S[0]+l*v-target)/Vs;
    return calc(start,S[0]+l*v,target,Vr,Vs);
}
point cut[2];
int R[2];
point p1, p2;
int main(){
    int T, n; cin>>T;
    while(T--){
        double Ts, Vr, Vs; cin>>Ts>>Vr>>Vs;
        double Xo, Yo, Xp, Yp; cin>>Xo>>Yo>>Xp>>Yp;
        point O(Xo,Yo), P(Xp,Yp);
        cin>>n;
        p.clear();
        double x, y;
        for(int i=0; i<n; i++){
            scanf("%lf%lf",&x,&y);
            p.push_back(point(x,y));
        }
        if(dlcmp(cross(p[1]-p[0],p[2]-p[1]))<0){
            reverse(p.begin(),p.end());
        }
        double carry_and_swim=1.0e20;
        for(int i=0; i<n; i++){
            carry_and_swim=min(carry_and_swim,distanceSP(line(p[i],p[(i+1)%n]),P));
        }
        carry_and_swim=2.0*carry_and_swim/Vs;
        double sum=0.0;
        for(int i=0; i<n; i++){
            direction[i]=dlcmp(cross(p[i]-O,p[(i+1)%n]-p[i]))>=0;
            sum+=abs(p[i]-p[(i+1)%n]);
        }
        int cnt=0;
        for(int i=0; i<n; i++){
            if(direction[i]!=direction[(i+1)%n]){
                R[cnt++]=(i+1)%n;
            }
            if(intersectSP(line(p[i],p[(i+1)%n]),O)){
                cut[0]=p[i];
                cut[1]=p[(i+1)%n];
                R[0]=i; R[1]=(i+1)%n;
            }
        }
        if(cnt!=0){
            if(direction[R[0]]!=0) swap(R[0],R[1]);
            cut[0]=p[R[0]]; cut[1]=p[R[1]];
        }
        double ans=1.0e20;
        int st=R[0], ed=R[1];
        if(ed<st) ed+=n;
        double ft=0.0;
        double ts, ts1, ts2, ret;
        for(int i=st; i<ed; i++){
            p1=p[i%n], p2=p[(i+1)%n];
            ret=solve(line(p1,p2),O,P,Vr,Vs,ts);
            if(ts+carry_and_swim-eps<=Ts){
                ans=min(ans,ret);
            }
            ft+=abs(p1-p2);
        }
        swap(st,ed);
        if(ed<st) ed+=n;
        double bk=0.0, al=(sum-ft), d1, d2;
        for(int i=st; i<ed; i++){
            p1=p[i%n], p2=p[(i+1)%n];
            d1=(abs(O-cut[1])+bk)/Vr+solve(line(p1,p2),p1,P,Vr,Vs,ts1);
            d2=(abs(O-cut[0])+al-bk-abs(p1-p2))/Vr+solve(line(p2,p1),p2,P,Vr,Vs,ts2);
            if(ts1+carry_and_swim-eps<=Ts){
                ans=min(ans,d1);
            }
            if(ts2+carry_and_swim-eps<=Ts){
                ans=min(ans,d2);
            }
            bk+=abs(p1-p2);
        }
        ans+=carry_and_swim;
        if(ans<=1.0e19) printf("%.2f\n",ans);
        else printf("-1\n");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值