多测,$T \leq 100, M \leq 100, N \leq 100$

给出 $M$ 个 $N$ 维空间中的点,满足两两之间距离为 1。

最多能再加入多少个点,使得仍然满足两两之间距离为 1,输出方案。


解决第一个问题,考虑归纳一下,在一维的时候,可以是一个直线,然后每加一维都可以多一个点。所以答案是 $M-N+1$。

然后考虑目前有 $C$ 个点,随机出来一个 $N$ 维点和这 $C$ 个点很大概率线性无关。所以我们可以容易的找到这个点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
using ar = valarray<double>;
double dot(const ar &x, const ar &y) {
double res = 0;
rep(i, sz(x)) res += 1. * x[i] * y[i];
return res;
}
const double eps = 1e-9;
void solve() {
int n, m;
cin >> n >> m;
vc<ar> v(m, ar(n));
rep(i, m) for (auto &d : v[i]) {
string s;
cin >> s;
d = stod(s);
}
uniform_real_distribution<double> rnd(-10, 10);
rep(i, m, n + 1) {
ar o(n);
for (auto vv : v)
o += vv;
o /= i;
auto vv = v;
for (auto &vvv : vv)
vvv -= o;
rep(k, i) rep(j, k) {
auto x = (vv[j]) * dot(vv[k], vv[j]);
vv[k] -= x;
if (dot(vv[k], vv[k]) < eps)
continue;
auto t = dot(vv[k], vv[k]);
vv[k] /= sqrt(t);
}
ar d(n);
for (auto &dd : d)
dd = rnd(rng);
rep(j, i) {
auto x = (vv[j]) * dot(d, vv[j]);
d -= x;
double t = dot(d, d);
d /= sqrt(t);
}
double l = sqrt(1. - dot(v[0] - o, v[0] - o));
v.pb(o + d * l);
}
static int cas = 0;
cout << "Case #" << ++cas << ": " << n + 1 - m << "\n";
cout << fixed << setprecision(10);
rep(i, m, n + 1) {
for (int j = 0; j < n; j++)
cout << v[i][j] << " \n"[j + 1 == n];
}
rep(i,n+1){
rep(j,n+1){
if(i==j)continue;
if(abs(dot(v[i]-v[j],v[i]-v[j])-1)>eps){
debug(i,j,dot(v[i]-v[j],v[i]-v[j]));
}
}
}
}