BZOJ 2458 最小三角形

题面

一个平面上有很多点,求他们中的点组成的周长最小的三角形的周长。

题解

平面最近点对差不多,也是先把区间内的点按x坐标从中间分开,递归处理,然后再处理横跨中线的三角形。

如何缩小范围?设左右两个子区间发现的最小周长是d,则与中线距离超过d / 2都没有用了,对于一个点,所有与它距离超过d / 2的点也都没有用。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long ll;
template <class T>
void read(T &x){
char c;
bool op = 0;
while(c = getchar(), c < '0' || c > '9')
if(c == '-') op = 1;
x = c - '0';
while(c = getchar(), c >= '0' && c <= '9')
x = x * 10 + c - '0';
if(op) x = -x;
}
template <class T>
void write(T x){
if(x < 0) putchar('-'), x = -x;
if(x >= 10) write(x / 10);
putchar('0' + x % 10);
} const int N = 200005;
int n;
struct point {
double x, y;
bool operator < (const point &b) const{
return x < b.x;
}
point operator - (const point &b){
return (point){x - b.x, y - b.y};
}
double norm(){
return sqrt(x * x + y * y);
}
} p[N], a[N], b[N], c[N]; double calc(point x, point y, point z){
return (x - y).norm() + (y - z).norm() + (z - x).norm();
}
double solve(int l, int r){
if(l == r) return 1e20;
int mid = (l + r) >> 1;
double xmid = (p[mid].x + p[mid + 1].x) / 2;
double d = min(solve(l, mid), solve(mid + 1, r));
int pos = l, pb = 0, pc = 0, pl = l, pr = mid + 1;
while(pos <= r)
if(pl <= mid && (pr > r || p[pl].y < p[pr].y)){
if(p[pl].x > xmid - d / 2) b[++pb] = p[pl];
a[pos++] = p[pl++];
}
else{
if(p[pr].x < xmid + d / 2) c[++pc] = p[pr];
a[pos++] = p[pr++];
}
for(int i = l; i <= r; i++)
p[i] = a[i];
if(l + 1 == r) return 1e20;
for(int i = 1, j = 1; i <= pb; i++){
while(j <= pc && b[i].y - c[j].y > d / 2) j++;
for(int k = j; k <= pc && abs(b[i].y - c[k].y) < d / 2; k++)
for(int h = k + 1; h <= pc && abs(b[i].y - c[h].y) < d / 2; h++)
d = min(d, calc(b[i], c[k], c[h]));
}
for(int i = 1, j = 1; i <= pc; i++){
while(j <= pb && c[i].y - b[j].y > d / 2) j++;
for(int k = j; k <= pb && abs(c[i].y - b[k].y) < d / 2; k++)
for(int h = k + 1; h <= pb && abs(c[i].y - b[h].y) < d / 2; h++)
d = min(d, calc(c[i], b[k], b[h]));
}
return d;
}
int main(){
read(n);
for(int i = 1; i <= n; i++)
scanf("%lf%lf", &p[i].x, &p[i].y);
sort(p + 1, p + n + 1);
printf("%.6lf\n", solve(1, n));
return 0;
}

BZOJ 2458 最小三角形 | 平面分治的更多相关文章

  1. BZOJ 2458: [BeiJing2011]最小三角形 | 平面分治

    题目: 给出若干个点 求三个点构成的周长最小的三角形的周长(我们认为共线的三点也算三角形) 题解: 可以参考平面最近点对的做法 只不过合并的时候改成枚举三个点更新周长最小值,其他的和最近点对大同小异 ...

  2. 【BZOJ 2458 最小三角形】

    Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1551  Solved: 549[Submit][Status][Discuss] Descripti ...

  3. bzoj-2458 2458: [BeiJing2011]最小三角形(计算几何+分治)

    题目链接: 2458: [BeiJing2011]最小三角形 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1101  Solved: 380 Des ...

  4. BZOJ2458 Beijing2011最小三角形(分治)

    类似于平面最近点对,考虑分治,即分别计算分割线两侧的最小三角形再考虑跨过线的三角形. 复杂度证明也是类似的,对于某一个点,在另一侧可能与其构成最小三角形的点在一个d*d/2的矩形内(两边之和大于第三边 ...

  5. [BJWC2011]最小三角形(分治+最近点对)

    题面:BJWC2011 最小三角形 \(solution:\) 昨天才学完平面最近点对,今天就要求平面最近的三个点,显然不是巧合. 仔细一思考,我们用来求平面最近点对的方法不就可以用到三个点上吗? 就 ...

  6. bzoj2458: [BeiJing2011]最小三角形(分治+几何)

    题目链接:bzoj2458: [BeiJing2011]最小三角形 学习推荐博客:分治法编程问题之最接近点对问题的算法分析 题解:先将所有点按x值排列,然后每次将当前区间[l,r]分成左右两半递归求解 ...

  7. Luogu4423 BJWC2011 最小三角形 平面最近点对

    传送门 题意:给出$N$个点,求其中周长最小的三角形(共线的也计算在内).$N \leq 2 \times 10^5$ 这道题唤起了我对平面最近点对的依稀记忆 考虑平面最近点对的分治,将分界线两边的求 ...

  8. bzoj 2458: [BeiJing2011]最小三角形 题解

    [前言]话说好久没有写题解了.到暑假了反而忙.o(╯□╰)o [原题] 2458: [BeiJing2011]最小三角形 Time Limit: 10 Sec  Memory Limit: 128 M ...

  9. 分治 - 计算几何 - BZOJ2458,[BeiJing2011]最小三角形

    http://www.lydsy.com/JudgeOnline/problem.php?id=2458 [BeiJing2011]最小三角形 描述 Frisk现在遇到了一个有趣的问题. 平面上有N个 ...

随机推荐

  1. Spring Boot之发送HTTP请求(RestTemplate详解)

    原文作者:微笑面对生活 https://www.javazhiyin.com/19714.html#comment-345 RestTemplate是Spring提供的用于访问Rest服务的客户端,R ...

  2. python 网页转pdf

    主要使用的是wkhtmltopdf的Python封装——pdfkit centos环境 安装:Install python-pdfkit pip install pdfkit 安装:Install w ...

  3. TensorFlow学习之路1-TensorFlow介绍

    TensorFlow是一个采用数据流图(data flow graphs),用于数据计算的开源软件库. 什么是数据流图? TensorFlow的数据流图是由“节点”(nodes)和“线”(edges) ...

  4. 【NLP】彻底搞懂BERT

    # 好久没更新博客了,有时候随手在本上写写,或者Evernote上记记,零零散散的笔记带来零零散散的记忆o(╥﹏╥)o..还是整理到博客上比较有整体性,也方便查阅~ 自google在2018年10月底 ...

  5. Linux 系统安全检查(shell)

    脚本内容: #!/bin/bash echo " (__)" echo " (oo)" echo " /------\/ " echo &q ...

  6. fdisk命令详解

    基础命令学习目录 原文链接:https://www.cnblogs.com/xiaofengkang/archive/2011/06/06/2073579.html fdisk -l 可以列出所有的分 ...

  7. 随手记录-linux-Linux目录结构

    转:别人的 装完Linux,首先需要弄清Linux 标准目录结构 / root —?启动Linux时使用的一些核心文件.如操作系统内核.引导程序Grub等. home —?存储普通用户的个人文件 ft ...

  8. 为什么你学过Java却忘光了——记第一次助教同学见面会

    大约两周之前,主讲老师刘志勇老师和我约定,让我上周四到课堂上和同学们认识.交流一下.一开始我不太明了去和大家见面要说些什么,也不太理解这么做的必要性是什么.但随着日子临近,我请教了周筠老师,周筠老师和 ...

  9. [buaa-SE-2017]结对项目-数独程序扩展

    结对项目-数独程序扩展 step1~step3:github:SE-Sudoku-Pair-master step4:github:SE-Sudoku-Pair-dev-combine step5:g ...

  10. java 线程的简单理解

    想要实现线程可以继承Thread也可以实现接口runnable,在类中重写 run()方法在主函数调用start方法就可以开辟线程. 对于java对象都有一个wait()和notify().notif ...