zoukankan      html  css  js  c++  java
  • Agc019_C Fountain Walk

    传送门

    题目大意

    给定网格图上起点和终点每个格子是长为$100$米的正方形,你可以沿着线走。

    平面上还有若干个关键点,以每个关键点为圆心,$10$为半径画圆,表示不能进入圆内的线,但是可以从圆周上走,求起点到终点的最短距离。

    保证任意两个关键点不在同一条水平或竖直的线上。

    题解

    先通过翻转网格图使得起点$S$在终点$Y$的左下方,由于有任意两两关键点不在同一水平竖直的线上,通过简单计算发现,我们只可能往右或往上冲着最终的终点走。

    随意我们只需要横纵坐标都在起点终点之间的关键点即可。

    对于一个关键点,如果经过它转$90°$,那么路程的长度就会减少,如果绕过半圆继续直走,那么路程长度就会增加。

    我们贪心取关键点。由于起点在左下方,终点在右上方,每次向右上方走,那么最终经过的关键点一定是一个上升的序列。

    我们只需要求这个上升的序列的长度即可。

    答案等于起点终点的曼哈顿距离$-$经过关键点的数量$ imes$绕$90$度省去的路程。

    注意,当最长上升子序列的长度达到$min{Y_T-Y_S+1,X_T-X_S+1}$时,说明至少绕过一个关键点的半圆,需要特判。

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define LL long long
    #define M 200020
    using namespace std;
    namespace IO{
    	const int BS=(1<<20)+5; int Top=0;
    	char Buffer[BS],OT[BS],*OS=OT,*HD,*TL,SS[20]; const char *fin=OT+BS-1;
    	char Getchar(){if(HD==TL){TL=(HD=Buffer)+fread(Buffer,1,BS,stdin);} return (HD==TL)?EOF:*HD++;}
    	void flush(){fwrite(OT,1,OS-OT,stdout);}
    	void Putchar(char c){*OS++ =c;if(OS==fin)flush(),OS=OT;}
    	void write(int x){
    		if(!x){Putchar('0');return;} if(x<0) x=-x,Putchar('-');
    		while(x) SS[++Top]=x%10,x/=10;
    		while(Top) Putchar(SS[Top]+'0'),--Top;
    	}
    	int read(){
    		int nm=0,fh=1; char cw=Getchar();
    		for(;!isdigit(cw);cw=Getchar()) if(cw=='-') fh=-fh;
    		for(;isdigit(cw);cw=Getchar()) nm=nm*10+(cw-'0');
    		return nm*fh;
    	}
    }
    using namespace IO;
    const double D=11.4159265358979323846264338328;
    const double K=-4.2920367320510338076867830836;
    int n,m,maxy,sx,sy,ex,ey,tot,c[M],pos[M],now; double ans;
    struct pot{
    	int X,Y; void gtin(){X=read(),Y=read(),maxy=max(maxy,Y+1);}
    	bool ft(){return X>=sx&&X<=ex&&Y>=sy&&Y<=ey;}
    	bool operator <(const pot&ot)const{return X<ot.X;}
    }p[M],t[M];
    int main(){
    	sx=read(),sy=read(),ex=read(),ey=read(),maxy=max(sy,ey);
    	if(sx>ex) swap(sx,ex),swap(sy,ey); n=read();
    	for(int i=1;i<=n;i++) p[i].gtin();
    	if(sy>ey){
    		for(int i=1;i<=n;i++) p[i].Y=maxy-p[i].Y;
    		sy=maxy-sy,ey=maxy-ey;
    	} sort(p+1,p+n+1),ans=(ey+ex-sy-sx)*100.0;
    	for(int i=1;i<=n;i++) if(p[i].ft()) t[++tot]=p[i];
    	memset(c,0x3f,sizeof(c)),c[0]=now=0;
    	for(int i=1;i<=tot;i++){
    		int l=1,r=now,md,res=0;
    		while(l<=r){md=((r+l)>>1);if(c[md]<t[i].Y) res=md,l=md+1;else r=md-1;}
    		if(res==now) now++; c[res+1]=min(c[res+1],t[i].Y);
    	}
    	if(now<=ex-sx&&now<=ey-sy) ans+=now*K;
    	else ans+=(now-1)*K+D; printf("%.13lf
    ",ans);
    	return 0;
    }
  • 相关阅读:
    WebADI_数据验证1_建立基于PLSQL返回FND Message验证(案例)
    PLSQL_案例优化系列_探寻表设计对SQL优化的重要性(案例4)
    PLSQL_案例优化系列_学习左右SQL执行计划各种方法(案例14)
    PLSQL_案例优化系列_探讨该如何分析读懂析执行计划(案例9)
    WebADI_配置设定08_设定参数WebADI Parameters List(案例)
    WebADI_案例实施01_开发一个基于R12.1.3的简单WebADI Desktop(案例)
    PLSQL_案例优化系列_洞察表连接与SQL优化之间关系(案例8)
    WebADI_配置设定09_设定组件WebADI Components(案例)
    WebADI_配置设定07_设定显示WebADI Content / Mapping(案例)
    WebADI_案例实施03_利用FND_LOAD安装和迁移WEBADI以及设定(案例)
  • 原文地址:https://www.cnblogs.com/OYJason/p/9849321.html
Copyright © 2011-2022 走看看