题目大意:平面上有$n$个点,要求你构造$m$条边(满足$m\leqslant40$),使得可以从原点到达给定的$n$个点(边必须平行于坐标轴)。并要求输出每一条边的方向,每条边必须都使用,无解输出$-1$。$n\leqslant1000$,点的坐标的绝对值$\leqslant10^9$,边长度$\leqslant10^{12}$
题解:因为所有的边必须使用,所以每一个点横纵坐标相加的奇偶性相同,不同就无解。发现若构造长度为$1,2,\cdots,2^n$的边,可以到达满足$|x|+|y|\leqslant2^{k+1}-1$且$|x|+|y|\equiv 1\pmod2$的所有点,若$|x|+|y|\equiv0\pmod2$就再加一条长度为$1$的边。并且发现$2^n>\sum\limits_{i=0}^{n-1}2^i$,故若从大到小考虑边,一定走横纵坐标中相差较多的一个方向。这样贪心枚举即可。
卡点:没开$\mathrm{long\ long}$,没有修改坐标位置
C++ Code:
#include <iostream> #include <algorithm> #include <cstdio> const int maxn = 1010, X[] = { 1, 0, -1, 0 }, Y[] = { 0, 1, 0, -1 }; int n, x[maxn], y[maxn], w[maxn], idx; void solve(long long x, long long y) { for (int i = 1; i <= idx; ++i) { char c; if (abs(x) > abs(y)) if (x < 0) x += w[i], c = 'L'; else x -= w[i], c = 'R'; else if (y < 0) y += w[i], c = 'D'; else y -= w[i], c = 'U'; std::cout << c; } std::cout.put('\n'); } int main() { std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0); std::cin >> n; for (int i = 1; i <= n; ++i) { std::cin >> x[i] >> y[i]; if ((x[i] + y[i] & 1) != (x[1] + y[1] & 1)) { std::cout << "-1\n"; return 0; } } for (int i = 30; ~i; --i) w[++idx] = 1 << i; if (!(x[1] + y[1] & 1)) w[++idx] = 1; std::cout << idx << '\n'; for (int i = 1; i < idx; ++i) std::cout << w[i] << ' '; std::cout << w[idx] << '\n'; for (int i = 1; i <= n; ++i) solve(x[i], y[i]); return 0; }