题目链接:

2458: [BeiJing2011]最小三角形

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1101  Solved: 380

Description

Xaviera现在遇到了一个有趣的问题。
平面上有N个点,Xaviera想找出周长最小的三角形。
由于点非常多,分布也非常乱,所以Xaviera想请你来解决这个问题。
为了减小问题的难度,这里的三角形也包括共线的三点。

Input

第一行包含一个整数N表示点的个数。
接下来N行每行有两个整数,表示这个点的坐标。

Output

输出只有一行,包含一个6位小数,为周长最短的三角形的周长(四舍五入)。

Sample Input

4
1 1
2 3
3 3
3 4

Sample Output

3.414214
 
题意:
 
思路:
 
像求最近点对那样进行分治,先按x左边排序,然后分治,找到左右两边较小的三角形周长d,然后再在以x=mid.x为中心线,左右宽各d/2的距离内和高d/2内的点,再求一次三角形最短周长就好了;
 
AC代码:
/**************************************************************
Problem: 2458
User: LittlePointer
Language: C++
Result: Accepted
Time:4696 ms
Memory:4416 kb
****************************************************************/ #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <bits/stdc++.h>
#include <stack>
#include <map> using namespace std; #define For(i,j,n) for(int i=j;i<=n;i++)
#define mst(ss,b) memset(ss,b,sizeof(ss)); typedef long long LL; template<class T> void read(T&num) {
char CH; bool F=false;
for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar());
for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar());
F && (num=-num);
}
int stk[70], tp;
template<class T> inline void print(T p) {
if(!p) { puts("0"); return; }
while(p) stk[++ tp] = p%10, p/=10;
while(tp) putchar(stk[tp--] + '0');
putchar('\n');
} const LL mod=1e9+7;
const double PI=acos(-1.0);
const LL inf=1e18+10;
const int N=2e5+10;
const int maxn=1e3+20;
const double eps=1e-12; int n;
struct node
{
int x,y;
}po[N],temp[N];
int cmp(node a,node b)
{
if(a.x==b.x)return a.y<b.y;
return a.x<b.x;
}
int cmp1(node a,node b)
{
return a.y<b.y;
}
double dis(int c,int e)
{
double fx=po[c].x*1.0,fy=po[c].y*1.0,ffx=po[e].x*1.0,ffy=po[e].y*1.0;
return sqrt((fx-ffx)*(fx-ffx)+(fy-ffy)*(fy-ffy));
}
double di(int c,int e)
{
double fx=temp[c].x*1.0,fy=temp[c].y*1.0,ffx=temp[e].x*1.0,ffy=temp[e].y*1.0;
return sqrt((fx-ffx)*(fx-ffx)+(fy-ffy)*(fy-ffy));
}
double solve(int l,int r)
{
if(r-l<=4)
{
double dis1,dist=inf;
for(int i=l;i<r;i++)
{
for(int j=i+1;j<r;j++)
{
dis1=dis(i,j);
for(int k=j+1;k<=r;k++)dist=min(dist,dis1+dis(i,k)+dis(j,k));
}
}
return dist;
}
int mid=(l+r)>>1;
double d1=solve(l,mid),d2=solve(mid+1,r);
double d=min(d1,d2);
int cnt=0;
for(int i=l;i<=r;i++)
{
double w=abs(po[mid].x-po[i].x);
if(2*w<=d)temp[++cnt]=po[i];
}
sort(temp+1,temp+cnt+1,cmp1);
double ans=d,ha;
for(int i=1;i<cnt;i++)
{
for(int j=i+1;j<cnt;j++)
{
ha=di(i,j);
if(ha>d*0.5)break;
for(int k=j+1;k<=cnt;k++)ans=min(ans,ha+di(i,k)+di(j,k));
}
}
return ans;
}
int main()
{
read(n);
For(i,1,n)
{
read(po[i].x);read(po[i].y);
}
sort(po+1,po+n+1,cmp);
double ans=solve(1,n);
printf("%.6lf\n",ans);
return 0;
}

  

bzoj-2458 2458: [BeiJing2011]最小三角形(计算几何+分治)的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. BZOJ 2458 最小三角形 | 平面分治

    BZOJ 2458 最小三角形 题面 一个平面上有很多点,求他们中的点组成的周长最小的三角形的周长. 题解 跟平面最近点对差不多,也是先把区间内的点按x坐标从中间分开,递归处理,然后再处理横跨中线的三 ...

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

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

  8. BZOJ 2458: [BeiJing2011]最小三角形 (分治)

    分治就是了. 类似于分治找最近/远点对. CODE #include <bits/stdc++.h> using namespace std; const double eps = 1e- ...

  9. [BZOJ]2458: [BeiJing2011]最小三角形

    题目大意:给出平面上n个点,求最小的由这些点组成的三角形的周长.(N<=200,000) 思路:点按x坐标排序后分治,每次取出与排在中间的点的横坐标相差不超当前答案一半的点,按y坐标排序后再暴力 ...

随机推荐

  1. Linux进程间通信(二) - 消息队列

    消息队列 消息队列是Linux IPC中很常用的一种通信方式,它通常用来在不同进程间发送特定格式的消息数据. 消息队列和之前讨论过的管道和FIFO有很大的区别,主要有以下两点(管道请查阅我的另一篇文章 ...

  2. windows常用dos命令

    常用命令: d: 回车   磁盘切换 dir: 查看该目录下所有的文件和文件夹: md: 创建文件加 rd: 删除目录 cd: 进入指定的目录 cd..:回退到上级目录 cd\  :回退到根目录 de ...

  3. SDOI2012 Round1 day2 拯救小云公主(dis)解题报告

    #include<cstdio> #include<cmath> #include<iostream> using namespace std; typedef l ...

  4. POJ 2965 The Pilots Brothers' refrigerator【枚举+dfs】

    题目:http://poj.org/problem?id=2965 来源:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=26732#pro ...

  5. cordova 获取地理位置

    第一步,引入插件 cordova plugin add cordova-plugin-geolocation 第二步, <!DOCTYPE html> <html> <h ...

  6. sqlalchemy——多表操作

    一对多:一对一 # one -- many class Students(Base): __tablename__ = "students" sid = Column(Intege ...

  7. MyBatis:学习笔记(4)——动态SQL

    MyBatis:学习笔记(4)——动态SQL

  8. || and && 理解

    逻辑或(||): 只要第一个值的布尔值为false,那么永远返回第二个值. 逻辑或属于短路操作,第一个值为true时,不再操作第二个值,且返回第一个值. 逻辑与(&&): 只要第一个值 ...

  9. java常用注解(更新中)

    注解根据来源可分为: 系统注解(自带的,取决于JDK版本).自定义注解及第三方注解 系统注解根据用途又可分为: java内置注解和元注解 根据运行机制(保留到什么时候)可分为: 源码注解.编译注解和运 ...

  10. hd acm2035

    求A^B的最后三位数表示的整数.说明:A^B的含义是“A的B次方” 思路:后三位只跟后三位相乘有关,所以可以每乘一次都对1000取余. 代码: #include <stdio.h>#inc ...