2012-A3-0021

从 Trac 迁移的文章

这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。

原文章内容如下:

题意:要从一条x坐标严格递增的折段一端走到另一端,只能经过上侧而不能穿越它,求最短路径长度。

最短路径显然是它的上凸包络线,于是只要按顺序一条条吧线段加入,用维护严格凸的折线段的栈就可以了。


{{{
#include<cstdio>
#include<cmath>
typedef double real;
typedef long long num;
size_t stack[1<<20],n,ps;
int x[1<<20],y[1<<20];

void push(size_t i){
    stack[++ps]=i;
}
void pop(){--ps;}
bool convex(size_t i,size_t j,size_t k){
    num
    xx1=(num)x[j]-x[i],
    yy1=(num)y[j]-y[i],
    xx2=(num)x[k]-x[i],
    yy2=(num)y[k]-y[i];
    return xx1*yy2>=xx2*yy1;
}
real dist(size_t i,size_t j){
    return hypot(x[i]-x[j],y[i]-y[j]);
}
int main(){

    for(real ans;scanf("%d",&n)==1;printf("%.2lf\n",ans)){
        for(size_t i=0;i<n;++i)
            scanf("%d%d",x+i,y+i);

        ps=0;push(0);push(1);
        for(size_t i=2;i<n;++i){
            for(;ps>1 && convex(stack[ps-1],stack[ps],i);)pop();
            push(i);
        }
        ans =0;
        for(size_t i=1;i<ps;++i)
            ans += dist(stack[i],stack[i+1]);
    }
}
}}}

题意:要从一条x坐标严格递增的折段一端走到另一端,只能经过上侧而不能穿越它,求最短路径长度。

最短路径显然是它的上凸包络线,于是只要按顺序一条条吧线段加入,用维护严格凸的折线段的栈就可以了。

#include<cstdio>
#include<cmath>
typedef double real;
typedef long long num;
size_t stack[1<<20],n,ps;
int x[1<<20],y[1<<20];
void push(size_t i){
    stack[++ps]=i;
}
void pop(){--ps;}
bool convex(size_t i,size_t j,size_t k){
    num
    xx1=(num)x[j]-x[i],
    yy1=(num)y[j]-y[i],
    xx2=(num)x[k]-x[i],
    yy2=(num)y[k]-y[i];
    return xx1*yy2>=xx2*yy1;
}
real dist(size_t i,size_t j){
    return hypot(x[i]-x[j],y[i]-y[j]);
}
int main(){
    for(real ans;scanf("%d",&n)==1;printf("%.2lf\n",ans)){
        for(size_t i=0;i<n;++i)
            scanf("%d%d",x+i,y+i);
        ps=0;push(0);push(1);
        for(size_t i=2;i<n;++i){
            for(;ps>1 && convex(stack[ps-1],stack[ps],i);)pop();
            push(i);
        }
        ans =0;
        for(size_t i=1;i<ps;++i)
            ans += dist(stack[i],stack[i+1]);
    }
}