AtCoder Grand Contest 019 C

来源:互联网 发布:国家外汇管理局 知乎 编辑:程序博客网 时间:2024/05/17 22:12

题目:传送门

思路:想要走最短距离,肯定是两点之间的曼哈顿距离最短,并且走过最多的喷泉。因为是最短,所以只能往终点方向移动,求一下起点到终点之间喷泉y坐标的最大单调序列,就能知道最多经过多少喷泉。有一种特殊情况,就是起点到终点的每一行或者每一列都有可走的喷泉(如下图),这样就要多算1/4个圆周。
这里写图片描述

代码如下:

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<vector>#include<algorithm>#define N 200005#define LL long long#define PI asin(1)*2using namespace std;struct point{    int x,y;    point(){};    point(int x,int y){        this->x=x;        this->y=y;    }};point s,t;int n; int dp[N],x[N];vector<point> p;int cmp(point a,point b){    return a.x<b.x;}int main(){    //cout<<PI<<endl;    while(~scanf("%d%d%d%d",&s.x,&s.y,&t.x,&t.y))    {        if(s.x>t.x) swap(s,t);        point ld=point(s.x,min(s.y,t.y));        point ru=point(t.x,max(t.y,s.y));        scanf("%d",&n);        point tmp;        while(n--)        {            scanf("%d%d",&tmp.x,&tmp.y);            if(tmp.x>=ld.x&&tmp.x<=ru.x&&tmp.y>=ld.y&&tmp.y<=ru.y)                p.push_back(tmp);        }        sort(p.begin(),p.end(),cmp);        double ans;        ans=abs(s.x-t.x)+abs(s.y-t.y);        ans*=100;        if(s.x==t.x||s.y==t.y)        {            if(p.size()!=0)                 ans=ans-10*2+10*PI;        }        else if(s.y<t.y&&p.size()>0)        {            int maxn;            x[1]=p[0].y;            int k=1;            dp[0]=1;            for(int i=1;i<p.size();i++)            {                if(x[k]<p[i].y)                {                    x[++k]=p[i].y;                    dp[i]=k;                }                else                {                    int l=1,r=k;                    while(l<=r)                    {                        int mid=(l+r)/2;                        if(x[mid]<=p[i].y)                            l=mid+1;                        else                            r=mid-1;                    }                     dp[i]=l;                    x[l]=p[i].y;                }            }            maxn=k;            if(maxn==abs(s.x-t.x)+1||maxn==abs(s.y-t.y)+1)                ans+=5*PI;            ans=ans-20*maxn+5*PI*maxn;        }        else if(s.y>t.y&&p.size()>0)        {            int maxn;            x[1]=p[p.size()-1].y;            int k=1;            dp[p.size()-1]=1;            for(int i=p.size()-2;i>=0;i--)            {                if(x[k]<p[i].y)                {                    x[++k]=p[i].y;                    dp[i]=k;                }                else                {                    int l=1,r=k;                    while(l<=r)                    {                        int mid=(l+r)/2;                        if(x[mid]<=p[i].y)                            l=mid+1;                        else                            r=mid-1;                    }                     dp[i]=l;                    x[l]=p[i].y;                }            }            maxn=k;            if(maxn==abs(s.x-t.x)+1||maxn==abs(s.y-t.y)+1)                ans+=5*PI;            ans=ans-20*maxn+5*PI*maxn;        }        printf("%.15lf\n",ans);        p.clear();    }}
原创粉丝点击