计算几何+三分求极值——cf1046I

枚举所有时刻,在两个时刻之间三分,因为距离肯定是个单峰函数

对卡精度又有了一些心得。。如果是db和某个int标准值比较,那么用sign,如果是两个db判大小,如三分,二分里精度要求高,那么不用sign会比较好

/*
从时间1-n段枚举这个过程
将每个人每个时间段的路程看做是线段,
求出两线段的最近点,如果<=d1且之前结束时间点有距离>=d2,那么ans++
*/
#include<bits/stdc++.h>
using namespace std;
typedef double db;
#define N 200005
const db eps=1e-6;
const db pi=acos(-1);
int sign(db k){if (k>eps) return 1; else if (k<-eps) return -1; return 0;}
int cmp(db k1,db k2){return sign(k1-k2);}
int inmid(db k1,db k2,db k3){return sign(k1-k3)*sign(k2-k3)<=0;}// k3 在 [k1,k2] 内
struct point{
    db x,y;
    point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};}
    point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};}
    point operator * (db k1) const{return (point){x*k1,y*k1};}
    point operator / (db k1) const{return (point){x/k1,y/k1};}
    int operator == (const point &k1) const{return cmp(x,k1.x)==0&&cmp(y,k1.y)==0;}
    db abs(){return sqrt(x*x+y*y);}
    db abs2(){return x*x+y*y;}
    db dis(point k1){return ((*this)-k1).abs();}
    point unit(){db w=abs(); return (point){x/w,y/w};}
};
int inmid(point k1,point k2,point k3){return inmid(k1.x,k2.x,k3.x)&&inmid(k1.y,k2.y,k3.y);}
db dot(point k1,point k2){return k1.x*k2.x+k1.y*k2.y;}
db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;}
int intersect(db l1,db r1,db l2,db r2){
    if (l1>r1) swap(l1,r1); if (l2>r2) swap(l2,r2); return cmp(r1,l2)!=-1&&cmp(r2,l1)!=-1;
}
int checkSS(point k1,point k2,point k3,point k4){
    return intersect(k1.x,k2.x,k3.x,k4.x)&&intersect(k1.y,k2.y,k3.y,k4.y)&&
    sign(cross(k3-k1,k4-k1))*sign(cross(k3-k2,k4-k2))<=0&&
    sign(cross(k1-k3,k2-k3))*sign(cross(k1-k4,k2-k4))<=0;
}
point proj(point k1,point k2,point q){ // q 到直线 k1,k2 的投影
    point k=k2-k1; return k1+k*(dot(q-k1,k)/k.abs2());
}
db disSP(point k1,point k2,point q){
    point k3=proj(k1,k2,q);
    if (inmid(k1,k2,k3)) return q.dis(k3); else return min(q.dis(k1),q.dis(k2));
}
db disSS(point k1,point k2,point k3,point k4){
    if (checkSS(k1,k2,k3,k4)) return 0;
    else return min(min(disSP(k1,k2,k3),disSP(k1,k2,k4)),min(disSP(k3,k4,k1),disSP(k3,k4,k2)));
}

point A[N],B[N];
int n,d1,d2,tot;

int main(){
    cin>>n>>d1>>d2;
    for(int i=1;i<=n;i++)
        cin>>A[i].x>>A[i].y>>B[i].x>>B[i].y;
    int flag=0;
    if(sign(A[1].dis(B[1])-d1)<=0)tot++,flag=1;
    db last=A[1].dis(B[1]);
    for(int i=2;i<=n;i++){
        point Va=A[i]-A[i-1],Vb=B[i]-B[i-1];
        db L=0,R=1,mid,midr,ans;//三分求最近距离
        while(R-L>eps){
            mid=(L+R)/2;
            midr=(mid+R)/2;
            db dis1=(A[i-1]+Va*mid).dis(B[i-1]+Vb*mid);
            db dis2=(A[i-1]+Va*midr).dis(B[i-1]+Vb*midr);
            if(dis1<dis2)
                ans=dis1,R=midr;
            else ans=dis2,L=mid;
        }
        if(sign(ans-d1)<=0){
            if(flag==0)tot++,flag=1;
        }
        last=A[i].dis(B[i]);
        if(sign(last-d2)>=0)flag=0;
    }
    cout<<tot<<‘\n‘;
}

原文地址:https://www.cnblogs.com/zsben991126/p/12537469.html

时间: 2024-10-29 21:24:02

计算几何+三分求极值——cf1046I的相关文章

hihoCoder #1142 : 三分求极值

#1142 : 三分·三分求极值 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 这一次我们就简单一点了,题目在此: 在直角坐标系中有一条抛物线y=ax^2+bx+c和一个点P(x,y),求点P到抛物线的最短距离d. 提示:三分法 输入 第1行:5个整数a,b,c,x,y.前三个数构成抛物线的参数,后两个数x,y表示P点坐标.-200≤a,b,c,x,y≤200 输出 第1行:1个实数d,保留3位小数(四舍五入) 样例输入 2 8 2 -2 6 样例输出 2.437

三分&#183;三分求极值 算法讲解和题目

题目: #1142 : 三分·三分求极值 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 这一次我们就简单一点了,题目在此: 在直角坐标系中有一条抛物线y=ax^2+bx+c和一个点P(x,y),求点P到抛物线的最短距离d. 提示:三分法 输入 第1行:5个整数a,b,c,x,y.前三个数构成抛物线的参数,后两个数x,y表示P点坐标.-200≤a,b,c,x,y≤200 输出 第1行:1个实数d,保留3位小数(四舍五入) 样例输入 2 8 2 -2 6 样例输出 2

#1142 : 三分&#183;三分求极值 ( 三分极值 )

#1142 : 三分·三分求极值 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 这一次我们就简单一点了,题目在此: [week40_1.PNG] 在直角坐标系中有一条抛物线y=ax^2+bx+c和一个点P(x,y),求点P到抛物线的最短距离d. 提示:三分法 输入 第1行:5个整数a,b,c,x,y.前三个数构成抛物线的参数,后两个数x,y表示P点坐标.-200≤a,b,c,x,y≤200 输出 第1行:1个实数d,保留3位小数(四舍五入) 样例输入 2 8 2

三分&#183;三分求极值

三分求极值 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 这一次我们就简单一点了,题目在此: 在直角坐标系中有一条抛物线y=ax^2+bx+c和一个点P(x,y),求点P到抛物线的最短距离d. 输入 第1行:5个整数a,b,c,x,y.前三个数构成抛物线的参数,后两个数x,y表示P点坐标.-200≤a,b,c,x,y≤200 输出 第1行:1个实数d,保留3位小数(四舍五入) 样例输入 2 8 2 -2 6 样例输出 2.437 #include <iostrea

hihocoder 1142 三分求极值【三分算法 模板应用】

#1142 : 三分·三分求极值 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 这一次我们就简单一点了,题目在此: 在直角坐标系中有一条抛物线y=ax^2+bx+c和一个点P(x,y),求点P到抛物线的最短距离d. 提示:三分法 输入 第1行:5个整数a,b,c,x,y.前三个数构成抛物线的参数,后两个数x,y表示P点坐标.-200≤a,b,c,x,y≤200 输出 第1行:1个实数d,保留3位小数(四舍五入) 样例输入 2 8 2 -2 6 样例输出 2.437

HLJU 1221: 高考签到题 (三分求极值)

1221: 高考签到题 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 9  Solved: 4 [Submit][Status][Web Board] Description 在直角坐标系中有一条抛物线y=ax^2+bx+c和一个点P(x,y),求点P到抛物线的最短距离d. Input 多组数据. 5个整数a,b,c,x,y.前三个数构成抛物线的参数,后两个数x,y表示P点坐标.-200≤a,b,c,x,y≤200 Output 1个实数d,保留

hihocoder 1142 三分&#183;三分求极值(三分)

题目1 : 三分·三分求极值 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 这一次我们就简单一点了,题目在此: 在直角坐标系中有一条抛物线y=ax^2+bx+c和一个点P(x,y),求点P到抛物线的最短距离d. 提示:三分法 输入 第1行:5个整数a,b,c,x,y.前三个数构成抛物线的参数,后两个数x,y表示P点坐标.-200≤a,b,c,x,y≤200 输出 第1行:1个实数d,保留3位小数(四舍五入) 样例输入 2 8 2 -2 6 样例输出 2.437 简

hiho一下 第四十周 题目1 : 三分&#183;三分求极值

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 这一次我们就简单一点了,题目在此: 在直角坐标系中有一条抛物线y=ax^2+bx+c和一个点P(x,y),求点P到抛物线的最短距离d. 提示:三分法 × 提示:三分法 在之前的几周中我们了解到二分法作为分治中最常见的方法,适用于单调函数,逼近求解某点的值. 但当函数是凸形函数时,二分法就无法适用,这时就需要用到三分法. 从三分法的名字中我们可以猜到,三分法是对于需要逼近的区间做三等分: 我们发现lm这个点比rm要低,那

三分求极值

三分算法解决凸形或者凹形函数的极值: 二分解决具有单调性的函数的极值: 凹形的可以通过*-1转化为凸形 mid = (Left + Right) / 2 midmid = (mid + Right) / 2; 如果mid靠近极值点,则Right = midmid: 否则(即midmid靠近极值点),则Left = mid; zoj3203 本题要求影子最长的长度. 在灯.人头.墙角成一条直线时影子长为a,在人到达墙角时影子长为b,我们可以写出人在这两点间时影子的方程:(x*H-D*h)/(x-D