CF201B Guess That Car! 题解
CF201B Guess That Car!
Content
停车场被划分为 \(n \times m\) 个小方格,每个小方格的边长为 \(4\) 米。每个小方格的正中心停着一辆车,价值为 \(C_{i,j}\)。
你只能站在某个网格点(即网格线的交点)上猜车。网格点坐标用 \((x,y)\) 表示,其中 \(x\) 从 \(0\) 到 \(n\),\(y\) 从 \(0\) 到 \(m\)。
若你与某车的欧几里得距离为 \(d\),则猜到这辆车需要花费 价值 × \(d²\) 的时间。
请你选择一个网格点,使得猜中所有车的总时间最小。若有多个最优点,优先输出 \(x\) 较小的,若 \(x\) 相同则输出 \(y\) 较小的。
Solution
1. 距离分解
设网格点坐标为 \((x,y)\),第 \(i\) 行第 \(j\) 列的车(\(0 \le i < n,\;0 \le j < m\))的中心位置为:
因为每格边长 \(4\) 米,中心在网格线偏移 \(2\) 米处。
那么欧几里得距离的平方为:
总花费:
总花费可以拆成横向部分与纵向部分之和,两部分相互独立。所以最优的 \(x\) 和 \(y\) 可以分别求。
2. 压缩信息
因为横向部分只与每一行的总价值有关,纵向部分只与每一列的总价值有关。设:
那么横向贡献为:
纵向贡献为:
总时间:
3. 枚举
\(x\) 的取值范围只有 \(0,1,\dots,n\),共 \(n+1\) 个,\(y\) 同理。
我们可以直接对每个 \(x\) 计算 \(F_x(x)\),取最小值。(\(y\) 同理。)
计算 \(F_x(x)\) 需要遍历所有 \(i\),复杂度 \(O(n)\),因此总复杂度 \(O(n^2 + m^2)\),在 \(n,m \le 1000\) 时炸不了。
为了避免浮点数,原式中含有 \(\frac12\),我们可以把所有值乘以 \(2\),最后再除回去。(为什么要避免浮点数呢,因为 我就是不喜欢 精度问题很难搞,可能会莫名其妙地变成“快乐的一只小青WA”。)
代码中的 cal_x(x) 计算的是:
同理 cal_y(y) = 4F_y(y)。
所以总时间为:
所以代码最后输出 4 * (bvx + bvy) 。
总时间复杂度 \(O(nm + n^2 + m^2)\),空间复杂度 \(O(n+m)\)。
AC Code
Tips:本人手欠用了#define int long long,据说不建议使用,请自行判断
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1005;
int n, m;
int r[N], c[N];
int cal_x(int x) { // 计算当横坐标为 x 时,所有车横向距离平方贡献之和(不含系数4)
int res = 0;
for (int i = 0; i < n; i++) {
int d = 2LL * x - 2LL * i - 1; // 2*(x - i - 0.5)
res += r[i] * d * d;
}
return res;
}
int cal_y(int y) { // 计算当纵坐标为 y 时,所有车纵向距离平方贡献之和(不含系数4)
int res = 0;
for (int i = 0; i < m; i++) {
int d = 2LL * y - 2LL * i - 1; // 2*(y - i - 0.5)
res += c[i] * d * d;
}
return res;
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> m;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
int v;
cin >> v;
r[i] += v;
c[j] += v;
}
}
int bx = 0, bvx = LLONG_MAX;
for (int i = 0; i <= n; i++) {
int val = cal_x(i);
if (val < bvx) {
bvx = val;
bx = i;
}
}
int by = 0, bvy = LLONG_MAX;
for (int i = 0; i <= m; i++) {
int val = cal_y(i);
if (val < bvy) {
bvy = val;
by = i;
}
}
int ans = 4LL * (bvx + bvy);
cout << ans << '\n' << bx << ' ' << by;
return 0;
}

浙公网安备 33010602011771号