P4423 [BJWC2011]最小三角形
题目链接:https://www.luogu.com.cn/problem/P4423
此题给定n个点,从n个点中选取3个点组成三角形的周长最小。
暴力枚举不要考虑。
那回想平面最近点对,平面最近点对是求一对点对之间的最小距离。
我们是否也可以用此种想法呢。
平面最近点对的代码,是针对一个点,求与另外一个点的距离,并不断的更新minx。
同样,我们这个题,不就是针对一个点,求与另外两个点的距离和最小。并不断的更新minx。
按此思路,我们将平面最近点对的模板进行更改
#include"stdio.h" #include"string.h" #include"vector" #include"math.h" #include"algorithm" using namespace std; typedef struct Node{ double x,y; int id; }Node; int n; Node node[200100]; Node tran[200100]; double minx = 1e20; bool same(double a, double b) { /// 1e-5精度意义下的浮点数相等 if(fabs(a-b) <= 1e-5) return true; return false; } int cmpx(Node a,Node b){ if(!same(a.x, b.x)) return a.x<b.x; return a.y<b.y; } int cmpy(Node a,Node b){ if(!same(a.y, b.y)) return a.y<b.y; return a.x<b.x; } void dist_minx(Node a,Node b,Node c){ double s1 = sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); double s2 = sqrt((a.x - c.x) * (a.x - c.x) + (a.y - c.y) * (a.y - c.y)); double s3 = sqrt((b.x - c.x) * (b.x - c.x) + (b.y - c.y) * (b.y - c.y)); minx = min(minx,s1 + s2 + s3); } void merge_node(int l,int mid,int r) { int t = 0; int i = l,j = mid + 1; while(i <= mid && j <= r) { if(node[i].y < node[j].y) { tran[++ t] = node[i]; i ++; continue; } else { tran[++ t] = node[j]; j ++; continue; } } while(i <= mid) tran[++ t] = node[i ++]; while(j <= r) tran[++ t] = node[j ++]; for(int i = l; i <= r; i ++) node[i] = tran[i - l + 1]; } void Blocking(int l,int r) { if(r - l <= 4) { for(int i = l; i < r; i ++) { for(int j = i + 1; j <= r; j ++) { for(int k = j + 1; k <= r; k ++) dist_minx(node[i],node[j],node[k]); } } sort(node + l,node + r + 1,cmpy); return ; } int mid = (l + r) >> 1; double midx = node[mid].x; Blocking(l,mid); Blocking(mid + 1,r); merge_node(l,mid,r); vector<Node> Q; for(int i = l; i <= r; i ++) { if(fabs(node[i].x - midx) >= minx / 2) continue; for(int j = Q.size() - 1; j >= 0; j --) { if(fabs(Q[j].y - node[i].y) >= minx) break; for(int k = j - 1; k >= 0; k --) dist_minx(Q[j],node[i],Q[k]); } Q.push_back(node[i]); } Q.clear(); return ; } int main() { scanf("%d",&n); for(int i = 1; i <= n; i ++) { scanf("%lf%lf",&node[i].x,&node[i].y); node[i].id = i; } sort(node + 1,node + n + 1,cmpx); Blocking(1,n); printf("%0.6lf\n",minx); }