【凸包】【Andrew算法】牛客 —message

…衆ロ難τιáo~ 提交于 2019-11-29 12:18:38

前置知识点

凸包:

概念

示例图(一)

示例图(一)

1  点集Q的凸包(convex hull)是指一个最小凸多边形,满足Q中的点或者在多边形边上或者在其内。右图中由红色线段表示的多边形就是点集Q={p0,p1,...p12}的凸包。

2  一组平面上的点,求一个包含所有点的最小的凸多边形,这就是凸包问题了。这可以形象地想成这样:在地上放置一些不可移动的木桩,用一根绳子把他们尽量紧地圈起来,并且为凸边形,这就是凸包了。

                                                                                                                                                                               ——百度百科

Andrew 算法

是一种求解凸包的一种基本算法

具体过程还不会,等本菜鸡学会了再回来填坑

 


题意:


           有 n 条直线 y=ax+b(a ≠ 0并且总是存在)。 m 次询问,每次询问给出一条直线 y=cx+d,求该直线与已知直线中交点横坐标最大的值是多少,如果没有交点则输出 "No cross"。

 


学习博客:https://blog.csdn.net/xbb224007/article/details/81158026

讲的超级详细,建议去学习


 

题解:

有两条直线

y=a*x+b

y=c*x+d

=>  x=  -(b-d)/(a-c)

这样问题求x的最大值就转化成了求斜率的最小值

这时候就根据凸包求解即可

 

具体讲解请看上述推荐博客


 

#include<iostream>
#include<algorithm>
#include<cmath>
#include<stdio.h>
#include<string.h>
#include<vector>
#include<map>
#pragma GCC optimize(2)
#if(__cplusplus == 201103L)
#include <unordered_map>
#include <unordered_set>
#else
#include <tr1/unordered_map>
#include <tr1/unordered_set>
namespace std
{
    using std::tr1::unordered_map;
    using std::tr1::unordered_set;
}
#endif
#include<tr1/unordered_map>
#include<set>
#include<stack>
#define debug cout<<"*"<<endl;
#define input(x) scanf("%d",&x)
#define output(x) printf("%d\n",x);
#define llinput(x) scanf("%lld",&x)
#define lloutput(x) printf("%lld\n",x);
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<string,int> psi;
typedef pair<char,char> pcc;
const int mod=1e9+7;
const int INF=1e9+7;
const int maxn=1e6+7;
const double E=2.718281828;
const double PI=acos(-1);
const double esp=1e-10;
/**
    Daily sentence:
    The wise man builds no hopes for the future, entertains no regrets for the past.
**/
struct Point{
    double x,y;
    int id;
    Point(){x=y=id=0;}
    Point(double _x,double _y)
    {
        x=_x;
        y=_y;
    }
}P[maxn],Convexhull[maxn];
double ans[maxn];   //记录每次询问的答案

Point operator + (Point p,Point q)
{
    return Point(p.x+q.x,p.y+q.y);
}
Point operator - (Point p,Point q)
{
    return Point(p.x-q.x,p.y-q.y);
}
Point operator * (Point p,double d)
{
    return Point(p.x*d,p.y*d);
}
Point operator / (Point p,double d)
{
    return Point(p.x/d,p.y/d);
}
int dcmp(double x){
    return fabs(x)<esp?0:x<0?-1:1;
}
bool operator <(Point p1,Point p2){
    return dcmp(p1.x-p2.x)<0||(dcmp(p1.x-p2.x)==0&&dcmp(p1.y-p2.y)<0);
}

double Dot(Point p,Point q) //点乘:(x1,y1)*(x2,y2)=x1*x2+y1*y2
{
    return p.x*q.x,p.y*q.y;
}
double Cross(Point p,Point q)   //叉乘:(x1,y1)×(x2,y2)=x1*y2-x2*y1
{
    return p.x*q.y-p.y*q.x;
}
double Get_slope(Point p)   //求斜率
{
    return p.y/p.x;
}
double Get_length(Point p)  //求长度
{
    return sqrt(p.x*p.x+p.y*p.y);
}
//Andrew算法求凸包
void Scan(int n)
{
    int top=0;
    for(int i=0;i<n;i++)
    {
        if(P[i].id)
        {
            if(!top)    continue;
            int l=0,r=top-1;
            while(l<r)
            {
                int mid=(l+r)>>1;
                if(Cross(Convexhull[mid+1]-Convexhull[mid],P[i]-Convexhull[mid])>0)
                    r=mid;
                else
                    l=mid+1;
            }
            ans[P[i].id]=min(ans[P[i].id],Get_slope(P[i]-Convexhull[l]));
        }
        else{
            while(top>1&&dcmp(Cross(P[i]-Convexhull[top-2],Convexhull[top-1]-Convexhull[top-2]))<0)
                top--;
            Convexhull[top++]=P[i];
        }
    }
}
void Andrew(int n)
{
    sort(P,P+n);Scan(n);
    reverse(P,P+n);Scan(n);
}
void Init()
{
    for(int i=0;i<maxn;i++)
        ans[i]=INF;
}
int main()
{
    Init();
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>P[i].x>>P[i].y;

    }
    int m;
    cin>>m;
    for(int i=n;i<n+m;i++)
    {
        P[i].id=i-n+1;
        cin>>P[i].x>>P[i].y;
    }
    Andrew(n+m);
    for(int i=1;i<=m;i++)
    {
        if(dcmp(ans[i])>0) printf("No cross\n");
        else    printf("%.12lf\n",-ans[i]);
    }
    return 0;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!