http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3762
思路:(轉自這篇文章)
先討論銳角/直角三角形的情況:
假設擁有最大高的三角形是ABC,如下圖
結合此圖我們可以看出最大高是點C到直線AB,在這種情況下,下列兩個結論至少有一個成立
1.點C是所有點中距離點A最遠的
2.點C是所有點中距離點B最遠的
反證:(這裏先證明在AB上側成立的情況)
首先過點C做直線A'B'平行於AB,再分別以點A、點B爲圓心,AC、BC長爲半徑做圓
假設點C對上述兩條結論均不成立,則還有一異於點C的點D至少滿足上述兩條結論之一,那麼點D只能在直線A'B'以上且在圓A、B外的區域內。
顯然,點D到直線AB的距離>點C到直線的距離,即△DAB的最大高>△CAB的最大高,與前提“擁有最大高的三角形是ABC”矛盾。
得證。
而在AB下側,那兩個圓的交點和點C是關於AB對稱的,道理也一樣,就不贅述了。
所以在△ABC是銳角/直角三角形時,“找最遠點”的策略一定是對的。
再看看鈍角三角形的情況:
這種情況發生在當點D位於點C的右下方,且在兩個圓外面時。
這時△ACD的最大高>△ACB的最大高(可以畫畫輔助線對比下)
所以在△ABC是鈍角三角形時,“找最遠點”的策略亦是對的。
因此我們可以對每個點,先O(n)枚舉距離它最遠的點,再O(n)枚舉三角形的另一個點就可以了,整體複雜度爲O(n^2)。
完整代碼:
/*510ms,176KB*/
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
struct P
{
double x, y;
} p[505];
///求pp到直線ab的距離
double dis(P &a, P &b, P &pp)
{
if (b.x != a.x)
{
double k = (b.y - a.y) / (b.x - a.x); ///直線斜率
return fabs((pp.y - a.y) - k * (pp.x - a.x)) / sqrt(1 + k * k); ///套公式
}
return fabs(pp.x - a.x);
}
int main()
{
int n, i, j, maxp;
double maxdis, tmp, ans;
while (~scanf("%d", &n))
{
ans = 0;
for (i = 0; i < n; i++) scanf("%lf%lf", &p[i].x, &p[i].y);
for (i = 0; i < n; i++)
{
maxdis = 0;
for (j = 0; j < n; j++)
{
if (i == j) continue;
tmp = hypot(p[i].x - p[j].x, p[i].y - p[j].y);
if (tmp > maxdis) maxdis = tmp, maxp = j;
}
for (j = 0; j < n; j++)
{
if (j == i || j == maxp) continue;
ans = max(dis(p[i], p[j], p[maxp]), ans);
//ans = max(dis(p[i], p[maxp], p[j]), ans); ///由於i-pmax這條邊一定不是最短邊,故垂足一定不在這條直線上
ans = max(dis(p[maxp], p[j], p[i]), ans); /// 最大高
}
}
printf("%f\n", ans);
}
return 0;
}