题目链接:https://ac.nowcoder.com/acm/contest/881/F

题目描述

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.
Print the value of 36×E. It can be proved that it is always an integer.

输入描述

The input consists of several test cases and is terminated by end-of-file.
Each test case contains six integers x1, y1, x2, y2, x3, y3
* |x1|,|y1|,|x2|,|y2|,|x3|,|y3|≤1e8
* There are at most 1e5 test cases.

输出描述

For each test case, print an integer which denotes the result.

示例

输入:

0 0 1 1 2 2
0 0 0 0 1 1
0 0 0 0 0 0

输出:

0
0
0

解题思路:
这个题答案是22倍的三角形面积,因为期望的意义是均值,这个均值肯定是个固定的值,所以不难想到答案的形式应该是一个常数*三角形面积的形式,关键就在于那个22是怎么推出来的了。

如图:

在三角形ABC中任取一点P,可将ΔABC划分为三个小三角形:ΔPAB,ΔPBC,ΔPAC
而对于三个小三角形的面积,临界条件是三个三角形面积相等,那么P应该位于ΔABC的重心上,即三条中线的交点。

重心主要有如下性质:
1.重心与三角形三个顶点的连线将三角形划分为三个面积相等的小三角形
2.重心将每一条中线划分为长度比为1:2的两部分

之后着眼于其中一个小三角形,如ΔPBC,那么P点应该在什么范围才能使SΔPBC在三个小三角形中最大呢?

如图,我们过P点分别作三条平行于ΔABC三条边的线(红线):
(中间的三条黑色短线为原三条中线的一部分)

我们将原来的每个小三角形的面积(即SΔABC/3)设为标准面积,那么我们很容易知道,当P点落在粉***域时SΔPBC肯定是最大的,因为此时P点位于平行于BC边的线以上,此时的SΔPBC大于标准面积,而P点同时又位于对应平行于其他两边的线以下(更靠近对应的底边),此时SΔPAB和SΔPAC均小于标准面积。

而当P点落在左侧的蓝***域时,SΔPAB小于标准面积,而SΔPBC和SΔPAC大于标准面积,但是P点在这个区域中更靠近平行于AC的红线,所以SΔPBC > SΔPAC,SΔPBC面积最大。
右侧蓝***域同理。

所以当P点落在上图蓝色和粉***域中时SΔPBC在三个小三角形的面积中最大,ΔPAC和ΔPAB同理,三个小三角形分别对应的使其面积最大的区域将ΔABC划分为三个等面积的部分,如下图:

那么,当我们在ΔABC内等可能任取一点P时,P点会等可能地落入上图的三个区域之一,所以题目所求的期望可以分解为 (P点分别落入上图三个区域中对应的三个期望之和) / 3,而三个区域是等面积的,所以三个对应期望是相等的,他们的均值等于一个区域的对应期望。

我们知道期望的意义是均值,我们在一个区域等可能的取点,那么点的期望位置就是该区域的重心。

答案的形式是常数*三角形面积,此时我们发现,这里的常数就是 (这个区域的重心到底边的距离) 和 (底边对应的高) 的比值,为方便计算,我们将ΔABC设为等边三角形,这样这个距离的垂线和高是共线的。


我们关注的区域由两个三角形组成,区域的重心即是两个三角形重心连线的中点(图中O点),我们要求的常数即是OH/AH的值。

PH = AH/3,FN = AH/2
所以QM = (FN + PH) / 2 = (5/12)AH = EH
那么AE = AH - EH = (7/12)AH
由重心的性质得OE = AE/3 = (1/3) * (7/12)AH = (7/36)AH
则OH = (7/36 + 5/12)AH = (22/36)AH
所求常数即是22/36

设三角形面积为S
题目要求36*E,而E = (22/36) * S,所以ans = 22 * S

关于三角形的面积,已知三个顶点坐标,我们可以用叉积来求,如ΔABC,S = (1/2) * ( 向量(AB) ✖ 向量(AC) )。

这里要注意,叉积有正有负,最终的答案为11倍叉积的绝对值。

AC代码:

#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <stack>
#include <string>
#include <set>
#include <vector>
#include <bitset>
using namespace std;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
const int MAXN = 3e5+10;
 
 
 
int main()
{
    ll x1, y1, x2, y2, x3, y3;
    while(~scanf("%lld%lld%lld%lld%lld%lld", &x1, &y1, &x2, &y2, &x3, &y3))
    {
        ll s = abs(x1*y2 + x2*y3 + x3*y1 - x1*y3 - x2*y1 - x3*y2);
        ll ans = 11 * s;
        printf("%lld\n", ans);
    }
    return 0;
}