牛客暑期赛第一场:Random Point in Triangle(三角形内的随机点)(数学期望)
Bobo has a triangle ABC with A(x1,y1),B(x2,y2 and C(x3,y3). Picking a point P uniformly in triangle ABC, he wants to know the expectation value E=max{SPAB,SPBC,SPCA}where SXYZ denotes the area of triangle XYZ.
波波有一个三角形,三角形三个顶点分别是A B C,在三角形内均匀取一个点P,他想知道E的期望值(E是三个子三角形的面积最大值)
Print the value of 36×E It can be proved that it is always an integer.
对答案乘36,事实证明它永远是个整数
这个题的突破口在于expectation value, in,uniformly这三个单词和事件空间内的期望值公式。
换句话说,就是在事件空间里不包含边界的区域内以等概率(此为均匀之意)随机取点,求它的数学期望值。我们根据题意知道,E只能是(1/3)倍的三角形面积(不三等分,总会有一个数大于1/3)和1倍的三角形面积之间的值,那么乘以36之后就是【12S,36S)区域(S是三角形面积),由于取整数,区间变为【12S,35S】,以12S作积分下限,35S作积分上限,1作积分函数(均匀取点即等概率取点)作积分,得到E[x]=23S,即23倍三角形面积。倘若不能使三个子三角形面积相等,那么区间为【13S,35S】,作积分得到E(x)=22S,即22倍三角形面积。
同样的,利用大量随机数所得结果的平均值也可判断出期望值。具体操作方案是生成大量随机点,然后利用线性规划(对于已知三角形的三边线性表达式)判断这些点是否在三角形内,然后按照题意求出三个子三角形的面积,并求最大值。求这些样本的和,除以落在三角形内部的点数,就是答案。
#include<pch.h>
#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
#include <map>
#include <algorithm>
#include <stack>
#include <iomanip>
#include <cstring>
#include <cmath>
#define DETERMINATION main
#define lldin(a) scanf_s("%lld", &a)
#define println(a) printf("%lld\n", a)
#define reset(a, b) memset(a, b, sizeof(a))
const int INF = 0x3f3f3f3f;
using namespace std;
const double PI = acos(-1);
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int mod = 1000000007;
const int tool_const = 19991126;
const int tool_const2 = 2000;
inline ll lldcin()
{
ll tmp = 0, si = 1;
char c;
c = getchar();
while (c > '9' || c < '0')
{
if (c == '-')
si = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
tmp = tmp * 10 + c - '0';
c = getchar();
}
return si * tmp;
}
///Untersee Boot IXD2(1942)
/**Although there will be many obstructs ahead,
the desire for victory still fills you with determination..**/
/**Last Remote**/
const int edges[3][2] = { -1,0,1,0,0,1 };//三角形三个顶点
ld func1(ld x, ld y)//各边的线性表达式
{
return y-x-1;
}
ld func2(ld x, ld y)
{
return x + y - 1;
}
ld func3(ld x, ld y)
{
return y;
}
ld calculation(ld x1, ld y1, ld x2, ld y2, ld x3, ld y3)//三角形行列式面积公式
{
return x1 * (y2 - y3) - y1 * (x2 - x3) + (x2*y3 - y2 * x3);
}
int DETERMINATION()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
ld area =fabs(calculation(1, 0, 0, 1, -1, 0))/2.0;
ld sum = 0,cnt=0;
ld mx1=0, mx2=0, mn1=0, mn2=0;
for (int i = 1; i <= 1000000; i++)
{
ld x = ((double(rand()) / RAND_MAX )* 2) - 1;
ld y =((double(rand()) / RAND_MAX) * 2) - 1;//生成随机实数,范围为【-1,1】
//mx1 = max(x, mx1), mx2 = max(y, mx2), mn1 = min(mn1, x), mn2 = min(y, mn2);
//cout << x << " " << y << endl;
if (func1(x, y) < 0 && func2(x, y) < 0 && func3(x, y) > 0)
{
cnt++;
ld tmp1, tmp2, tmp3;
tmp1 = fabs(calculation(x, y, 1, 0, -1, 0))/2;
tmp2 = fabs(calculation(x, y, 0, 1, -1, 0))/2;
tmp3 = fabs(calculation(x, y, 0, 1, 1, 0))/2;//求子三角形面积
ld tmpans = max(max(tmp1, tmp2), max(tmp2, tmp3));
sum += tmpans;
}
}
//cout << mx1 << " " << mx2 << " " << mn1 << " " << mn2 << endl;
sum /= cnt;//求均值
cout << (sum*36/ area) << endl;
return 0;
}

浙公网安备 33010602011771号