bzoj2458 [BeiJing2011]最小三角形
2458: [BeiJing2011]最小三角形
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1671 Solved: 582
[Submit][Status][Discuss]
Description
Xaviera现在遇到了一个有趣的问题。
平面上有N个点,Xaviera想找出周长最小的三角形。
由于点非常多,分布也非常乱,所以Xaviera想请你来解决这个问题。
为了减小问题的难度,这里的三角形也包括共线的三点。
Input
第一行包含一个整数N表示点的个数。
接下来N行每行有两个整数,表示这个点的坐标。
Output
输出只有一行,包含一个6位小数,为周长最短的三角形的周长(四舍五入)。
Sample Input
4
1 1
2 3
3 3
3 4
1 1
2 3
3 3
3 4
Sample Output
3.414214
HINT
100%的数据中N≤200000。
Source
分析:平面上最近距离点的模板.实际上就是把求两个点变成了求三个点,多一层枚举即可.一个小小的优化:若左右搜到的答案为res,则找的点到中间点的x坐标差的绝对值≤res / 2.
尽管读入是整数,但最好还是用实数读入,不然以后处理进制转换很容易WA.
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; int n,cnt; struct node { double x,y; }e[200010],p[200010]; double dist(node a,node b) { return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } bool cmp(node a,node b) { return a.x < b.x; } bool cmp2(node a,node b) { return a.y < b.y; } double solve(int l,int r) { if (l + 2 == r) return dist(e[l],e[l + 1]) + dist(e[l + 1],e[r]) + dist(e[l],e[r]); if (l + 1 >= r) return 1e20; int mid = (l + r) >> 1; double res = min(solve(l,mid - 1),solve(mid + 1,r)); cnt = 0; for (int i = l; i <= r; i++) if (fabs(e[mid].x - e[i].x) <= res / 2.0) p[++cnt] = e[i]; sort(p + 1,p + 1 + cnt,cmp2); for (int i = 1; i <= cnt; i++) { for (int j = i + 1; j <= cnt; j++) { if (p[j].y - p[i].y > res / 2.0) break; for (int k = j + 1; k <= cnt; k++) { if (p[k].y - p[i].y > res / 2.0) break; res = min(res,dist(p[i],p[j]) + dist(p[i],p[k]) + dist(p[j],p[k])); } } } return res; } int main() { scanf("%d",&n); for (int i = 1; i <= n; i++) scanf("%lf%lf",&e[i].x,&e[i].y); sort(e + 1,e + 1 + n,cmp); printf("%.6lf\n",solve(1,n)); return 0; }