ARC172D Distance Ranking
Description
\(n\) 个 \(n\) 维空间中的点,每个点的坐标都是整数。给定 \(\frac{(n-1)n}2\) 个点对距离的大小关系,构造一个满足条件的解。答案中整数坐标 \(\le 10^8,3\le n\le 20\)
Solution
超,2936!
根据 \(n=3\) 的 “把三个点放到一个线段上” 的做法行不通就应该能猜到 \(n\) 个点必须用 \(n\) 维而不是 \(n-1\) 或者 \(n-2\) 维(也就是你把三个点放到三角形中考虑)
不过现在是 \(n\) 个点 \(n\) 个维度,所以令坐标矩阵 \(p\) 满足 \(p_{i,j}=[i=j]\) 就能满足所有点之间的距离都相等(\(\sqrt 2\))
既然这样,我们试图给将这些点进行 微扰,具体而言,将原先坐标矩阵 \(\begin{bmatrix}1\ 0\ 0 \\0\ 1\ 0\\0\ 0\ 1 \end{bmatrix}\) 变成 \(\begin{bmatrix}1+\epsilon_{1,1}\ 0+\epsilon_{1,2}\ 0+\epsilon_{1,3} \\0+\epsilon_{2,1}\ 1+\epsilon_{2,2}\ 0+\epsilon_{2,3}\\0+\epsilon_{3,1}\ 0+\epsilon_{3,2}\ 1+\epsilon_{3,3} \end{bmatrix}\)
这里 \(\epsilon_{i,j}\) 是非常小的量,比如 \(10^{-5}\) 级别,我们通过将它们同时乘 \(10^{8}\) 而变成整数,同时调整他们的相对大小来实现距离的偏序关系。
直接写出来点之间距离表达式,注意到比较距离大小(比如 \(d(p_i,p_j)\) 和 \(d({p_k,p_l})\)),本质上就是比较 \(\epsilon_{i,j}+\epsilon_{j,i}\) 和 \(\epsilon_{k,l}+\epsilon_{k,l}\) 的大小(这里我们省略了两个 \(\epsilon\) 相乘的项,因为 \(n\) 个 \(\epsilon\) 相加仍然和 \(1\) 有很大差距)
假设 \(i<j\) 一种直截了当的方法就是让 \(p_{j,i}=0,p_{i,j}=rank_{i,j}\) 即 \((i,j)\) 对子在点对距离中的排名
Code
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
template<typename T>inline void ckmax(T &x,T y){x=x<y?y:x;}
template<typename T>inline void ckmin(T &x,T y){x=x>y?y:x;}
template<typename T=int>inline T read(){
T res=0,f=1; char k;
while(!isdigit(k=getchar())) if(k=='-') f=-1;
while(isdigit(k)) res=res*10+k-'0',k=getchar();
return res*f;
}
template<typename T>inline void print(T x,bool fl=1){
if(x<0) putchar('-'),x=-x;
if(x>=10) print(x/10,0);
putchar(x%10+'0');
if(fl) putchar('\n');
}
int main(){
int n=read();
vector<vector<int> >ans(n,vector<int>(n));
for(int i=1;i<=n*(n-1)/2;++i){
int a=read(),b=read();
if(a>b) swap(a,b);
--a; --b;
ans[a][b]=n*(n-1)/2-i+1;
}
rep(i,0,n-1) ans[i][i]=1e8;
rep(i,0,n-1){
rep(j,0,n-1) printf("%d ",ans[i][j]);
putchar('\n');
}
return 0;
}