zoukankan      html  css  js  c++  java
  • [AtCoder 2702]Fountain Walk

    Problem Statement

    In the city of Nevermore, there are 108 streets and 108 avenues, both numbered from0 to 108−1. All streets run straight from west to east, and all avenues run straight from south to north. The distance between neighboring streets and between neighboring avenues is exactly 100 meters.

    Every street intersects every avenue. Every intersection can be described by pair(x,y), where x is avenue ID and y is street ID.

    There are N fountains in the city, situated at intersections (Xi,Yi). Unlike normal intersections, there's a circle with radius 10 meters centered at the intersection, and there are no road parts inside this circle.

    The picture below shows an example of how a part of the city with roads and fountains may look like.

    1f931bf0c98ec6f07e612b0282cdb094.png

    City governors don't like encountering more than one fountain while moving along the same road. Therefore, every street contains at most one fountain on it, as well as every avenue.

    Citizens can move along streets, avenues and fountain perimeters. What is the shortest distance one needs to cover in order to get from intersection (x1,y1) to intersection (x2,y2)?

    Constraints

    • 0≤x1,y1,x2,y2<108
    • 1≤N≤200,000
    • 0≤Xi,Yi<108
    • XiXj for ij
    • YiYj for ij
    • Intersections (x1,y1) and (x2,y2) are different and don't contain fountains.
    • All input values are integers.

    Input

    Input is given from Standard Input in the following format:

    x1 y1 x2 y2
    N
    X1 Y1
    X2 Y2
    :
    XN YN
    

    Output

    Print the shortest possible distance one needs to cover in order to get from intersection (x1,y1) to intersection (x2,y2), in meters. Your answer will be considered correct if its absolute or relative error doesn't exceed 10−11.

    Sample Input 1

    1 1 6 5
    3
    3 2
    5 3
    2 4
    

    Sample Output 1

    891.415926535897938
    

    One possible shortest path is shown on the picture below. The path starts at the blue point, finishes at the purple point and follows along the red line.

    c49e52b9b79003f61b8a6efa5dad8ba3.png

    Sample Input 2

    3 5 6 4
    3
    3 2
    5 3
    2 4
    

    Sample Output 2

    400.000000000000000
    
    f9090ab734c89424c413f3b583376990.png

    Sample Input 3

    4 2 2 2
    3
    3 2
    5 3
    2 4
    

    Sample Output 3

    211.415926535897938
    
    4b76416161f27cad20333a9ac636e00f.png
     

    愚人节赛的第二题(滑稽)。
    首先可以知道,每经过一个喷泉,都只可能走1/4或1/2个圆。而且走半个圆相对直走来说更长,走1/4个圆相对直走来说更短。
    同时,由于只有一个询问,所以可以把考虑的范围缩到以边(S,T)为对角线的矩形中。
    而且,每一小段的长度都远大于走喷泉节省的距离,且喷泉数量很有限,所以最优解中不存在绕路走喷泉的情况。
    设S在矩形左下角,T在矩形右上角,易知此时最优解中经过的喷泉的x,y坐标单调上升,LIS直接刚。
    需要注意的是,若矩形的每一行(列)都存在要走的喷泉,则必有一个喷泉要走整圈(否则会走出矩形)。
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #define y1 Y1
    using namespace std;
    const int maxn=200005,inf=1e8;
    const double qarc=acos(-1)*5.0;
    int n,cnt,x1,x2,y1,y2;
    int f[maxn],g[maxn],b[maxn];
    struct p{int x,y;}a[maxn];
    inline int read(){
        int x=0,f=1;char ch=getchar();
        for(;ch<'0'||ch>'9';f=ch=='-'?-1:1,ch=getchar());
        for(;ch>='0'&&ch<='9';x=x*10+ch-48,ch=getchar());
        return x*f;
    }
    bool cmp(p a,p b){return a.x<b.x;}
    int main(){
        x1=read();y1=read();x2=read();y2=read();n=read();
        for(int i=1;i<=n;i++)a[i].x=read(),a[i].y=read();
        if(x1>x2){
            x1=inf-x1;x2=inf-x2;
            for(int i=1;i<=n;i++)a[i].x=inf-a[i].x;
        }
        if(y1>y2){
            y1=inf-y1;y2=inf-y2;
            for(int i=1;i<=n;i++)a[i].y=inf-a[i].y;
        }
        sort(a+1,a+n+1,cmp);
        int tot=0,ans1=0;
        for(int i=1;i<=n;i++)
            if(a[i].x>=x1&&a[i].x<=x2&&a[i].y>=y1&&a[i].y<=y2)
                b[++tot]=a[i].y;
        for(int i=1;i<=tot;i++){
            f[i]=lower_bound(g+1,g+ans1+1,b[i])-g;
            if(f[i]>ans1)ans1=f[i],g[ans1]=b[i];
            else g[f[i]]=min(g[f[i]],b[i]);
        }
        double ans=(double)(x2+y2-x1-y1)*100.0;
        ans-=ans1*(20-qarc);
        if(ans1==min(y2-y1+1,x2-x1+1))ans+=qarc;
        printf("%.15lf",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    docker 笔记
    XML解析
    P1047 校门外的树
    4829 [DP]数字三角形升级版
    1996 矿场搭建
    5524 割点
    4817 江哥的dp题d
    4809 江哥的dp题c
    4816 江哥的dp题b
    4815 江哥的dp题a
  • 原文地址:https://www.cnblogs.com/Marser/p/8724173.html
Copyright © 2011-2022 走看看