AtCoder Grand Contest 019 C - Fountain Walk (LIS)

题目:传送门

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

代码如下:

#include
#include
#include
#include
#include
#include
#define N 200005
#define LL long long
#define PI asin(1)*2
using 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 p;

int cmp(point a,point b)
{
    return a.xint main()
{
    //cout<
    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.y0)
        {
            int maxn;
            x[1]=p[0].y;
            int k=1;
            dp[0]=1;
            for(int i=1;iif(x[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]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();
    }
}

你可能感兴趣的:(动态规划dp)