当前位置: 首页 > article >正文

WSPD:平面最近邻+t-spanner+近似欧氏距离MST(程设实习)

哎呀打字麻烦死了还是贴PPT吧

前言

感觉这个东西还是有点厉害的。

定义

在这里插入图片描述

构造

在这里插入图片描述
可以证明这样构造的WSPD大小为 O ( n ϵ − d log ⁡ △ ) O(n\epsilon^{-d}\log\triangle) O(nϵdlog) △ \triangle 为值域。

平面最近邻

构造 ϵ = 1 \epsilon=1 ϵ=1 的WASD,只需对于所有 ∣ A i ∣ = ∣ B i ∣ = 1 |A_i|=|B_i|=1 Ai=Bi=1 的里面的两个点的距离向答案贡献一次即可。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define uint unsigned int
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("ok\n")
inline ll read(){
	ll x(0),f(1);char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return f*x;
}

const int N=2e5+100;
const double eps=1.0;

double mx=1<<30;
int n,m;

struct point{
	double x[3];
}; 
void print(point o,int flag){
	printf("(%.0lf %.0lf %.0lf) ",o.x[0],o.x[1],o.x[2]);
	if(flag) puts("");
}
inline double dis(const point &u,const point &v){
	double res=0;
	for(int i=0;i<3;i++){
		res+=(u.x[i]-v.x[i])*(u.x[i]-v.x[i]);
	}
	return sqrt(res);
}
struct tree{
	double l[3],r[3];
	point o;
	int son[8];
}tr[N*20];
const double c=sqrt(3);
inline double diam(int x){
	if(tr[x].son[0]==-1) return 0;
	return c*(tr[x].r[0]-tr[x].l[0]);
}
inline double dis(const tree &u,const tree &v){
	
	double ans=0;
	for(int i=0;i<3;i++){
		double d;
		if(u.r[i]>v.l[i]&&v.r[i]>u.l[i]) d=0;
		else if(u.l[i]>v.r[i]) d=u.l[i]-v.r[i];
		else d=v.l[i]-u.r[i];
		ans+=d*d;
		//printf("i=%d d=%lf flag=%d %d %lf>%lf\n",i,d,u.r[i]+1e-9>v.l[i],u.r[i]<v.r[i]+1e-9u.r[i],v.r[i]+1e-9);
	}
	return sqrt(ans);
}

int tot;
int build(vector<point>ve,vector<double> le,vector<double> ri){
	if(ve.empty()) return 0;
	int now=++tot;
	for(int i=0;i<3;i++) tr[now].l[i]=le[i],tr[now].r[i]=ri[i];
	if(ve.size()==1){
		tr[now].o=ve[0];
		tr[now].son[0]=-1;
		return now;
	}
	vector<double> mid;
	for(int i=0;i<3;i++) mid.push_back((le[i]+ri[i])/2);
	vector<point>v[8];
	for(point o:ve){
		int id=0;
		for(int i=0;i<3;i++){
			if(o.x[i]>mid[i]) id|=(1<<i);
		}
		v[id].push_back(o);
	}
	for(int id=0;id<8;id++){
		vector<double>l,r;
		for(int i=0;i<3;i++){
			if(id>>i&1){
				l.push_back(mid[i]);
				r.push_back(ri[i]);
			}
			else{
				l.push_back(le[i]);
				r.push_back(mid[i]);
			}
		}
		tr[now].son[id]=build(v[id],l,r);
	}
	return now;
}


double ans=1e18;
vector<point>tmp;
void dfs(int x){
	if(!x) return;
	if(tr[x].son[0]==-1){
		tmp.push_back(tr[x].o);
		return;
	}
	for(int i=0;i<8;i++) dfs(tr[x].son[i]);
}
void getpt(int x){
	tmp.clear();
	dfs(x);
	for(point o:tmp) print(o,0);
	puts("");
}
inline void get(int x,int y){
	//printf("\nget: (%d %d)\n",x,y);
	//getpt(x);
	//getpt(y);
	//puts("");
	if(tr[x].son[0]==-1&&tr[y].son[0]==-1){
		ans=min(ans,dis(tr[x].o,tr[y].o));
		//print(tr[x].o,0);
		//print(tr[y].o,1);
	}
	return;
}
void find(int u,int v){
	if(u*v==0) return;
	if(u==v&&tr[u].son[0]==-1) return;
	if(diam(u)<diam(v)) swap(u,v);
	//printf("find: (%d %d) diam=%lf %lf dis=%lf\n",u,v,diam(u),diam(v),dis(tr[u],tr[v]));
	//getpt(u);
	//getpt(v);
	if(diam(u)<=eps*dis(tr[u],tr[v])){//find a WSPD
		get(u,v);
		return;
	}
	for(int i=0;i<8;i++) find(tr[u].son[i],v);
}

int main() {
	
	//freopen("a.in","r",stdin);
	//freopen("a.out","w",stdout);
    	
	n=read();
	vector<point>ve;
	ve.resize(n);
	for(point &o:ve){
		for(int i=0;i<3;i++) o.x[i]=read();
	}
	
	if(0)for(int i=0;i<n;i++){
		for(int j=i+1;j<n;j++) printf("(%d %d) dis=%lf\n",i,j,dis(ve[i],ve[j]));
	}
	
	vector<double>l,r;
	for(int i=0;i<3;i++){
		l.push_back(0);
		r.push_back(mx);
	}
	int rt=build(ve,l,r);
	find(rt,rt);
    
    printf("%.2lf\n",ans);
    return 0;
}

t-spanner

定义

在这里插入图片描述

构造

构造 ϵ 4 − W S P D \frac{\epsilon}{4}-WSPD 4ϵWSPD,然后对于每对 A i , B i A_i,B_i Ai,Bi 各选取一个代表点连边即可。
可以考虑递归归纳证明。

近似欧氏距离MST

直接在 t-spanner 上做MST即可。
读者自证不难


http://www.kler.cn/a/6247.html

相关文章:

  • Python 敲电子木鱼,见机甲佛祖,修赛博真经
  • QT 控件定义为智能指针引发的bug
  • D类音频应用EMI管理
  • Java 深拷贝全面解析
  • 抖音小程序登录(前端通过tt.login获取code换取openId)
  • 一个简单的机器学习实战例程,使用Scikit-Learn库来完成一个常见的分类任务——**鸢尾花数据集(Iris Dataset)**的分类
  • 搭建Git服务器-Git钩子的使用
  • 进化吧Java接口兽
  • 代码生成- 引言
  • 编译报错pcl_conversions、及pcl_rosConfig解决方法
  • 位图和布隆过滤器
  • 4.3---Spring框架之Spring中bean的注入方式---(深入版本)
  • 免费CDN-CloudFlare的使用教程
  • STM32个人笔记-I2S
  • Git操作之 git add 撤销、git commit 撤销
  • 原神服务器架设教程(服务器命令代码)
  • C++相关面试题总结一——内存、关键字、STL、指针、排序、Lambda
  • 【iOS】—— 类和对象底层探索
  • SpringBoot国际化配置
  • 通过 NFTScan 追踪 NFT 钻石手持仓
  • mysql binlog 一直追加写,磁盘满了怎么办?
  • Win11启用IE方法
  • 超详细WindowsJDK1.8与JDK11版本切换教程
  • PCB模块化设计11——VGA高速PCB布局布线设计规范
  • nanovg绘图库的编译与使用
  • 【Python】数据容器--列表常用方法