double d = min(a, b);
int i = upper_bound(data + q, data + (q + t) / 2, make_pair(x_mid - d, INF)) - data;
int jj = upper_bound(data + (q + t) / 2, data + t, make_pair(x_mid + d, INF)) - data;
for(; i < (q + t) / 2; i++)
{
for(int j = (q + t) / 2; j < jj; j++)
{
if(data[i].first - data[j].first >= d)
{
break;
}
else
{
d = min(d, dist(data[i], data[j]));
}
}
}
return d;
}
int main()
{
int N;
scanf(“%d”, &N);
for(int i = 0; i < N; i++)
{
scanf(“%lf %lf”, &data[i].first, &data[i].second);
}
sort(data, data + N);
double jg = deal(0, N);
printf(“%.4lf\n”, jg);
}
第二种:我们在递归处理的同时,按 y坐标 进行归并排序
这样的话我们无法判断直接判断哪个点的 x坐标 离中间点的 横坐标 距离小于 d ,所以我们遍历所有点,当点的 x坐标 在距离中间点的 横坐标 距离小于 d 时进行处理,处理方法为,对一定范围的点,进行遍历比较,如下图
【相当于我们对于所有点遍历一次,如果 x坐标 在范围内,我们便对阴影区域进行遍历,由于有 d 的限制,所以除去自身,该矩形阴影内最多还有 5 个点。】
缺点:我们遍历了所有点,有 x坐标 距离中间点横坐标超过 d 的多余情况
代码如下(这种在P1429中所耗 1.19s / 8.03MB / 1.45KB )
double deal(int q, int t)
{
if(t - q == 1)
{
return INF;
}
double x_mid = data[(q+t)/2].first;
double a = deal(q, (q + t) / 2);
double b = deal((q + t) / 2, t);
double d = min(a, b);
inplace_merge(data + q, data + (q + t) / 2, data + t, cmp);
vector dian;
for(int i = q; i < t; i++)
{
if(data[i].first <= x_mid - d || data[i].first >= x_mid + d)
{
continue;
}
for(int j = dian.size() - 1; j >= 0; j–)
{
if(data[i].second - data[dian[j]].second >= d)
{
break;
}
d = min(d, dist(data[i], data[dian[j]]));
}
dian.push_back(i);
}
return d;
}
第三种:因为同边的点的最小值已经求出为 d ,所以不用 同边 的之间再次比较,所以我们可以分开两个vector容器分别存左边和右边的 x坐标 在范围内的点
但是这种会产生一种问题,如果在 中间点的横坐标 的点,我们不知道它属于左边还是右边,所以我们左右两边都得存放,且要和左右两边都比较一次
这种优化很不明显,甚至当在中间点的横坐标上的点多了的时候会退化,且原本范围内也就只用匹配最多五次,改了也就省了一两次匹配,还增加了大量代码量
缺点多着
代码如下( 1.58s / 8.07MB / 2.25KB )
double deal(int q, int t)
{
if(t - q == 1)
{
return INF;
}
double x_mid = data[(q+t)/2].first;
double a = deal(q, (q + t) / 2);
double b = deal((q + t) / 2, t);
double d = min(a, b);
inplace_merge(data + q, data + (q + t) / 2, data + t, cmp);
vector right;
vector left;
for(int i = q; i < t; i++)
{
if(data[i].first <= x_mid - d || data[i].first >= x_mid + d)
{
continue;
}
if(data[i].first <= x_mid)
{
left.push_back(i);
for(int j = right.size() - 1; j >= 0; j–)
{
if(i == left[j])
{
continue;
}
if(data[i].second - data[right[j]].second >= d)
{
break;
}
else
最后更多分享:前端字节跳动真题解析
or(int j = right.size() - 1; j >= 0; j–)
{
if(i == left[j])
{
continue;
}
if(data[i].second - data[right[j]].second >= d)
{
break;
}
else
最后更多分享:前端字节跳动真题解析
- [外链图片转存中…(img-cjJAUmGw-1718097470184)]