牛客挑战赛33 C 艾伦的立体机动装置(几何体的最短距离 三分)

本文主要是介绍牛客挑战赛33 C 艾伦的立体机动装置(几何体的最短距离 三分),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


 

OJ题号

牛客挑战赛33 C 艾伦的立体机动装置

https://ac.nowcoder.com/acm/contest/1115/C

简单题意

中文题

正解思路

  • 因为下表面是可以走的,所以不能直接算s点和t点展开的直线距离。
  • 枚举经过下表面的每一条边,再在每条边上三分求出最短距离。注意最短距离的初始值要设为不经过下表面任何一条边的最短距离。

slen记录每个顶点到s点的距离,getdis是获得上表面或下表面的两点距离,finddis是获得如果经过下表面某个点的路程距离,tridiv三分。因为我的下标是从0开始的,所以s点是p[s-1]。

详细链接

 

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int s,t,n;
double ans,slen[100001],h;
pair<double,double>p[100001];
inline double getdis(pair<double,double>p1,pair<double,double>p2)
{return sqrt((p1.first-p2.first)*(p1.first-p2.first)+(p1.second-p2.second)*(p1.second-p2.second));
}
inline double finddis(pair<double,double>now,int l,int r)
{double len = min(slen[l]+getdis(p[l],now),slen[r]+getdis(p[r],now));return sqrt(h*h+len*len)+getdis(now,p[t-1]);
}
inline double tridiv(int l,int r)
{double minn = 0x3f3f3f3f;pair<double,double> left = p[l];pair<double,double> right = p[r];while(getdis(left,right)>1e-3){pair<double,double> first = make_pair((2*left.first+right.first)/3,(2*left.second+right.second)/3);pair<double,double> second = make_pair((left.first+2*right.first)/3,(left.second+2*right.second)/3);double firdis = finddis(first,l,r);double secdis = finddis(second,l,r);if(firdis>secdis){left = first;minn = min(minn,secdis);}else{right = second;minn = min(minn,firdis);}}return minn;
}
int main()
{scanf("%d%lf",&n,&h);for(int i = 0; i<n; i++)scanf("%lf%lf",&p[i].first,&p[i].second);scanf("%d%d",&s,&t);double s1 = 0,s2 = 0,sum = 0;int last = s-1;slen[last] = 0;for(int i = s%n; i!=s-1; i++,i%=n){double len = getdis(p[last],p[i]);sum+=len;slen[i] = slen[last]+len;last = i;}sum+=getdis(p[last],p[s-1]);for(int i = 0; i<n; i++)slen[i] = min(slen[i],sum-slen[i]);ans = sqrt(slen[t-1]*slen[t-1]+h*h);last = n-1;for(int i = 0; i<n; i++,last++,last%=n)ans = min(ans,tridiv(last,i));printf("%.6lf",ans);return 0;
}

 

 

 

 

 

点与线模板,但我不会用这个模板做这道题。

#include <bits/stdc++.h>using namespace std;
const double eps = 1e-8;
const double inf = 1e20;
const double pi = acos(-1.0);
const int N = 1e5+7;
//Compares a double to zero
int sgn(double x){if(fabs(x) < eps)return 0;if(x < 0)return-1;else return 1;
}
//square of a double
inline double sqr(double x){return x*x;}struct Point{double x,y;
Point(){}Point(double _x,double _y){x = _x;y = _y;}void input(){scanf("%lf%lf",&x,&y);}void output(){printf("%.2f-%.2f\n",x,y);}bool operator == (Point b)const{return sgn(x-b.x) == 0 && sgn(y-b.y) == 0;}bool operator < (Point b)const{return sgn(x-b.x)== 0-sgn(y-b.y)?0:x<b.x;}Point operator-(const Point &b)const{return Point(x-b.x,y-b.y);}//叉积double operator ^(const Point &b)const{return x*b.y-y*b.x;}//点积double operator *(const Point &b)const{return x*b.x + y*b.y;}//返回长度double len(){return hypot(x,y);//库函数}//返回长度的平方double len2(){return x*x + y*y;}//返回两点的距离double distance(Point p){return hypot(x-p.x,y-p.y);}Point operator +(const Point &b)const{return Point(x+b.x,y+b.y);}Point operator *(const double &k)const{return Point(x*k,y*k);}Point operator /(const double &k)const{return Point(x/k,y/k);}//计算 pa 和 pb 的夹角//就是求这个点看 a,b 所成的夹角//测试 LightOJ1203double rad(Point a,Point b){Point p = *this;return fabs(atan2( fabs((a-p)^(b-p)),(a-p)*(b-p) ));}//化为长度为 r 的向量Point trunc(double r){double l = len();if(!sgn(l))return *this;r /= l;return Point(x*r,y*r);}//逆时针旋转 90 度Point rotleft(){return Point(-y,x);}//顺时针旋转 90 度Point rotright(){return Point(y,-x);}//绕着 p 点逆时针旋转 anglePoint rotate(Point p,double angle){Point v = (*this)-p;double c = cos(angle), s = sin(angle);return Point(p.x + v.x*c-v.y*s,p.y + v.x*s + v.y*c);}
}p[N];
struct Line{Point s,e;
Line(){}Line(Point _s,Point _e){s = _s;e = _e;}bool operator ==(Line v){return (s == v.s)&&(e == v.e);}//根据一个点和倾斜角 angle 确定直线,0<=angle<piLine(Point p,double angle){s = p;if(sgn(angle-pi/2) == 0){e = (s + Point(0,1));}else{e = (s + Point(1,tan(angle)));}}//ax+by+c=0Line(double a,double b,double c){if(sgn(a) == 0){s = Point(0,-c/b);e = Point(1,-c/b);}else if(sgn(b) == 0){s = Point(-c/a,0);e = Point(-c/a,1);}else{s = Point(0,-c/b);e = Point(1,(-c-a)/b);}}void input(){s.input();e.input();}void adjust(){if(e < s){swap(s,e);}}//求线段长度double length(){return s.distance(e);}//返回直线倾斜角 0<=angle<pidouble angle(){double k = atan2(e.y-s.y,e.x-s.x);if(sgn(k) < 0)k += pi;if(sgn(k-pi) == 0)k-= pi;return k;}//点和直线关系//1 在左侧//2 在右侧//3 在直线上int relation(Point p){int c = sgn((p-s)^(e-s));if(c < 0)return 1;else if(c > 0)return 2;else return 3;}// 点在线段上的判断bool pointonseg(Point p){return sgn((p-s)^(e-s)) == 0 && sgn((p-s)*(p-e)) <= 0;}//两向量平行 (对应直线平行或重合)bool parallel(Line v){return sgn((e-s)^(v.e-v.s)) == 0;}//两线段相交判断//2 规范相交//1 非规范相交//0 不相交int segcrossseg(Line v){int d1 = sgn((e-s)^(v.s-s));int d2 = sgn((e-s)^(v.e-s));int d3 = sgn((v.e-v.s)^(s-v.s));int d4 = sgn((v.e-v.s)^(e-v.s));if( (d1^d2)==-2 && (d3^d4)==-2 )return 2;return (d1==0 && sgn((v.s-s)*(v.s-e))<=0) ||(d2==0 && sgn((v.e-s)*(v.e-e))<=0) ||(d3==0 && sgn((s-v.s)*(s-v.e))<=0) ||(d4==0 && sgn((e-v.s)*(e-v.e))<=0);}//直线和线段相交判断//-*this line -v seg//2 规范相交//1 非规范相交//0 不相交int linecrossseg(Line v){int d1 = sgn((e-s)^(v.s-s));int d2 = sgn((e-s)^(v.e-s));if((d1^d2)==-2) return 2;return (d1==0||d2==0);}//两直线关系//0 平行//1 重合//2 相交int linecrossline(Line v){if((*this).parallel(v))return v.relation(s)==3;return 2;}//求两直线的交点//要保证两直线不平行或重合Point crosspoint(Line v){double a1 = (v.e-v.s)^(s-v.s);double a2 = (v.e-v.s)^(e-v.s);return Point((s.x*a2-e.x*a1)/(a2-a1),(s.y*a2-e.y*a1)/(a2-a1));}//点到直线的距离double dispointtoline(Point p){return fabs((p-s)^(e-s))/length();}//点到线段的距离double dispointtoseg(Point p){if(sgn((p-s)*(e-s))<0 || sgn((p-e)*(s-e))<0)return min(p.distance(s),p.distance(e));return dispointtoline(p);}//返回线段到线段的距离//前提是两线段不相交,相交距离就是 0 了double dissegtoseg(Line v){return min(min(dispointtoseg(v.s),dispointtoseg(v.e)),min(v.dispointtoseg(s),v.dispointtoseg(e)));}//返回点 p 在直线上的投影Point lineprog(Point p){return s + ( ((e-s)*((e-s)*(p-s)))/((e-s).len2()) );}//返回点 p 关于直线的对称点Point symmetrypoint(Point p){Point q = lineprog(p);return Point(2*q.x-p.x,2*q.y-p.y);}
};
double sum[N],ans=1e18;
int s,t;
void work(Point x,Line tmp,int i){Line res=Line(x,p[t]);//printf("%lf\n",res.length());if(res.linecrossseg(tmp)!=0){ans=min(ans,res.length());    }
}
int main(){int n,h;scanf("%d%d",&n,&h);for(int i=0;i<n;i++){p[i].input();}scanf("%d%d",&s,&t);--s; --t;for(int i=1;i<n;i++){sum[i]=sum[i-1]+p[i-1].distance(p[i]);}double tot=sum[n]=sum[n-1]+p[n-1].distance(p[0]);for(int i=0;i<n;i++){Point x=p[i],y=p[(i+1)%n];Point z=(x-y).rotleft();z=z*(h*1.0/z.len());Point t=y+z;Line tmp=Line(t,t+z.rotleft());//printf("%lf\n",tot);double len;if(s>=i+1){len=sum[s]-sum[i+1];}else{len=tot-sum[i+1]+sum[s];}Point l,r;l=t+(tmp.e-tmp.s)/tmp.length()*len;r=t+(tmp.e-tmp.s)/tmp.length()*(len-tot);
//        cout<<i<<" "<<r.x<<" "<<r.y<<endl;work(l,Line(x,y),i);work(r,Line(x,y),i);    }printf("%.6lf\n",ans);
}

 

这篇关于牛客挑战赛33 C 艾伦的立体机动装置(几何体的最短距离 三分)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/379127

相关文章

电力系统中的A类在线监测装置—APView400

随着电力系统的日益复杂和人们对电能质量要求的提高,电能质量在线监测装置在电力系统中得到广泛应用。目前,市场上的在线监测装置主要分为A类和B类两种类型,A类和B类在线监测装置主要区别在于应用场景、技术参数、通讯协议和扩展性。选择时应根据实际需求和应用场景综合考虑,并定期维护和校准。电能质量在线监测装置是用于实时监测电力系统中的电能质量参数的设备。 APView400电能质量A类在线监测装置以其多核

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

牛客小白月赛100部分题解

比赛地址:牛客小白月赛100_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ A.ACM中的A题 #include<bits/stdc++.h>using namespace std;#define ll long long#define ull = unsigned long longvoid solve() {ll a,b,c;cin>>a>>b>

牛客小白月赛100(A,B,C,D,E,F三元环计数)

比赛链接 官方讲解 这场比较简单,ABC都很签到,D是个不太裸需要预处理的 B F S BFS BFS 搜索,E是调和级数暴力枚举,F是三元环计数。三元环考的比较少,没见过可能会偏难。 A ACM中的A题 思路: 就是枚举每个边变成原来的两倍,然后看看两短边之和是否大于第三边即可。 不能只给最短边乘 2 2 2,比如 1 4 8 这组数据,也不能只给第二短边乘 2 2 2,比

笔试强训,[NOIP2002普及组]过河卒牛客.游游的水果大礼包牛客.买卖股票的最好时机(二)二叉树非递归前序遍历

目录 [NOIP2002普及组]过河卒 牛客.游游的水果大礼包 牛客.买卖股票的最好时机(二) 二叉树非递归前序遍历 [NOIP2002普及组]过河卒 题里面给的提示很有用,那个马的关系,后面就注意,dp需要作为long的类型。 import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息publ

每日OJ_牛客_求和(递归深搜)

目录 牛客_求和(递归深搜) 解析代码 牛客_求和(递归深搜) 求和_好未来笔试题_牛客网 解析代码         递归中每次累加一个新的数,如果累加和大于等于目标,结束递归。此时如果累加和正好等于目标,则打印组合。向上回退搜索其它组合。此题本身就是一个搜索的过程,找到所有的组合。 #include <iostream>#include <cmath>#in

除了立体监控,Clickhouse在腾讯实现了哪些牛逼应用

点击上方蓝色字体,选择“设为星标” 回复”资源“获取更多资源 大数据技术与架构 点击右侧关注,大数据开发领域最强公众号! 暴走大数据 点击右侧关注,暴走大数据! Clickhouse的部署和管理 Clickhouse自身是一个非常强大的数据处理引擎,因为它非常专注数据处理的计算效率这一块,因此它周边的一些管理插件,其实还是比较弱的。 大家在做大数据的平台,以及在做一些平台产品的时候,其

svg无功补偿装置脉冲封锁怎么解除

SVG(Static Var Generator,静态无功发生器)脉冲封锁是一种保护机制,用于防止装置在异常情况下继续运行,从而避免对电力系统造成进一步的损害。如果SVG进入脉冲封锁状态,通常需要执行特定的步骤来解除封锁并恢复正常运行。以下是解除SVG脉冲封锁的一般步骤: 1. 检查故障原因 故障诊断:首先,查看SVG的故障记录或报警信息,确定导致脉冲封锁的具体原因。常见的原因包括过电流、过电

基于51单片机的倒计时装置proteus仿真

地址: https://pan.baidu.com/s/1p9xDKXaulyx-PyP6dURp-g 提取码:1234 仿真图: 芯片/模块的特点: AT89C52/AT89C51简介: AT89C52/AT89C51是一款经典的8位单片机,是意法半导体(STMicroelectronics)公司生产的一系列单片机之一。它基于8051内核,并具有许多与其兼容的特性。 主要特点如下:

牛客《剑指Offer》 -- 数值的整数次方

题目描述 给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。 思路 特别注意负数的情况,出现负数,将其转化为正数然后求倒数。 class Solution {public:double Power(double base, int exponent) {double total = 1;bool flag = false