Newcoder 141 I.Expected Size of Random Convex Hull(凸包-Graham扫描法+撒点)

186 篇文章 0 订阅
85 篇文章 0 订阅

Description

给出一个二维平面三角形的三个顶点坐标,问在该三角形内随机选取 n n 个点,他们形成的凸包的顶点数量期望值

Input

输入三个点的横纵坐标xi,yi以及点数 n n

(109xi,yi109,3n10)

Output

输出凸包顶点的期望值

Sample Input

0 0
1 0
2 1
3

Sample Output

3.000000000000

Solution

n n 很小,本地暴力撒点求期望即可,发现规律为3+23+24+...+2n1

Code

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define maxn 15
const double eps=1e-8;
const double PI=acos(-1.0);
struct Point
{
    double x,y;
    double k;
    Point(){}
    Point(double _x,double _y)
    {
        x=_x;y=_y;
    }
    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;
    }
};
int sgn(double x)
{
    if(fabs(x)<eps) return 0;
    if(x<0) return -1;
    else return 1;
}
double dist(Point a,Point b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
Point list[maxn];
int Stack[maxn],top;
//相对于list[0]的极角排序
bool _cmp(Point p1,Point p2)
{
    double tmp=(p1-list[0])^(p2-list[0]);
    if(sgn(tmp)>0)return true;
    else if(sgn(tmp)==0&&sgn(dist(p1,list[0])-dist(p2,list[0]))<=0)return true;
    else return false;
}
int Graham(int n)
{
    Point p0;
    int k=0;
    p0=list[0];
    //找最下边的一个点
    for(int i=1;i<n;i++)
    {
        if((p0.y>list[i].y)||(p0.y==list[i].y&&p0.x>list[i].x))
        {
            p0=list[i];
            k=i;
        }
    }
    swap(list[k],list[0]);
    sort(list+1,list+n,_cmp);
    if(n==1)
    {
        top=1;
        Stack[0]=0;
        return 1;
    }
    if(n==2)
    {
        top=2;
        Stack[0]=0;
        Stack[1]=1;
        return 2;
    }
    Stack[0]=0;
    Stack[1]=1;
    top=2;
    for(int i=2;i<n;i++)
    {
        while(top>1&&sgn((list[Stack[top-1]]-list[Stack[top-2]])^(list[i]-list[Stack[top-2]]))<=0)
            top--;
        Stack[top++]=i;
    }
    return top;
}
void random(int n)
{
    for(int i=0;i<n;i++)
    {
        double x=rand(),y=rand();
        x/=RAND_MAX,y/=RAND_MAX;
        if(x<y)swap(x,y);
        list[i].x=x,list[i].y=y;
    }
}
int main()
{
    /*
    for(int n=3;n<=10;n++)
    {
        srand(time(0));
        int cnt=1e7;
        double p=cnt,ans=0;
        while(cnt--)
        {
            random(n);
            ans+=Graham(n);
        }
        printf("n=%d %.5f\n",n,ans/p);
    }*/
    int a;
    for(int i=1;i<=6;i++)scanf("%d",&a);
    int n;
    scanf("%d",&n);
    double ans=3;
    for(int i=3;i<n;i++)ans+=2.0/i;
    printf("%.5f\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值