HYSBZ/BZOJ 1038 [ZJOI2008] 瞭望塔 - 計算幾何__棧

來源:互聯網
上載者:User

題目描述 分析:

題目中說的“可以看見”means 在折線的每段所在直線朝x軸正方向,直線的左邊一片地區(其實就是折線的每段所在直線的上面)
所以我們要求的就是此題折線所在直線相交構成的一個底朝下的凸殼(類似二次函數a>0的樣子),網上都說這個是求半平面交,這裡就不那麼高大上了,直接求吧。 Solution : 先對Lines按照斜率大小排序,用一個棧來維護形成凸殼的直線。
如果當前直線與stack [top-2] (棧的倒數第二個元素)的交點橫座標小於stack [top-1]與stack [top-2] 的交點橫座標,那麼stack [top-1]這個元素出隊(依據是:當前的直線相對倒數第一條直線對倒數第二條直線更優,就不要倒數第一條了) 特別注意如果有斜率相等的直線要取與y軸截距最大的那條,而且不能算交點。。 因為求得是兩段折線之間的距離,顯然距離的計算可以表示為分段函數,而每一段函數都是一次函數的形式,那麼距離也應該是一次函數的形式(或者常函數),極值都是在折線的交點(折點)處取。
分為兩個部分算。
Part 1:凸殼折點對應的距離 Part 2:題目給出的折線的折點對應的距離。

#include<cstdio>#include<cmath>#include<algorithm>using namespace std;#define MAXN 300const double eps=1e-12;const double INF=1e20;struct Point{    int x,y;}a[MAXN+10];struct Line{    double k,b;}L[MAXN+10],stak[MAXN+10];int n,top;double ans=INF,cro[MAXN+10];double Getk(Point a,Point b){    return 1.0*(a.y-b.y)/(a.x-b.x);}void read(){    scanf("%d",&n);    for(int i=1;i<=n;i++)        scanf("%d",&a[i].x);    for(int i=1;i<=n;i++)        scanf("%d",&a[i].y);    for(int i=1;i<n;i++){        L[i].k=Getk(a[i],a[i+1]);        L[i].b=1.0*a[i].y-1.0*a[i].x*L[i].k;    }}bool cmp(Line a,Line b){    if(fabs(a.k-b.k)<eps) return a.b<b.b;    return a.k<b.k;}double GetCrossP(Line a,Line b){ //Get Crossover Point    return (a.b-b.b)/(b.k-a.k);}void GetConvex(){    sort(L+1,L+n,cmp);    stak[top++]=L[1];    for(int i=2;i<n;i++){        while(top){            if(fabs(stak[top-1].k-L[i].k)<eps) top--;            else if(top>1&&GetCrossP(L[i],stak[top-2])<=GetCrossP(stak[top-2],stak[top-1]))                top--;            else                break;        }        stak[top++]=L[i];    }}double Gety(Line a,double x0){    return a.k*x0+a.b;}void Getans(){    //Part 1    for(int i=1;i<top;i++){        double x0=GetCrossP(stak[i-1],stak[i]);        cro[i]=x0;        int k=-1;        for(int j=1;j<n;j++)            if(x0<=1.0*a[j+1].x){                k=j;                break;            }        if(k==-1) continue;        Line t;        t.k=Getk(a[k],a[k+1]);        t.b=1.0*a[k].y-1.0*a[k].x*t.k;        double tmp=Gety(stak[i],x0)-Gety(t,x0);        if(tmp>=0.0)            ans=min(ans,tmp);    }    //Part 2    for(int i=1;i<=n;i++){        int k=-1;        for(int j=1;j<top;j++)            if(1.0*a[i].x<=cro[j]){                k=j-1;                break;            }        if(k==-1) continue;        double tmp=Gety(stak[k],1.0*a[i].x)-1.0*a[i].y;        if(tmp>=0.0)            ans=min(ans,tmp);    }    printf("%.3lf\n",ans);}int main(){    read();    GetConvex();    Getans();    return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.