「ARC103D」Robot Arms「构造」
题意
给定n个点,你需要找到一个合适的m和d1,d2,...,dm,使得从原点出发每次向四个方向的某一个走di个单位,最终到达(xt,yt)。输出m和d数组;对于t=1→n输出方向。
n≤103,坐标范围109
题解
如果这些点(xt,yt),xt+yt的奇偶性不同那无解
如果xt+yt为偶数,我们先让d1=1,这样转换为xt+yt为奇数的情况。
奇数怎么做?二进制构造。
一:考虑d(k)=1,2,4,...,2k这样的集合,能走到所有|x|+|y|≤2k+1−1的点(且和为奇数)
证明:https://blog.csdn.net/qq_37555704/article/details/83217444#_14 这里搬来的图。
对于d(k)−d(k−1)的区域(新区域),直接走一步就到了(如上图红到紫)
对于原来就能到达的区域,我们可以从内部走到内部。
二:考虑怎么找到方案。
证明:d(k)能走到到点满足min
证明大概就是最值在|x|=2^k-1,|y|=2^k时取到,调整发现不优。
我们只要每次从d(k)走到d(k-1)即可,到d(0)时就成功了
通过画图分析,每次把绝对值大的减小就可以从d(k)走到d(k-1)。
那么这个题就没了。还有我们上面是d(k)走到d(k-1),实际上是反过来的,因此输出的字母要注意取反。
#include <algorithm>
#include <cstdio>
using namespace std;
const int N = 1010;
int n, m, x[N], y[N], d[N];
bool tg[N];
int main() {
scanf("%d", &n);
for(int i = 1; i <= n; i ++) {
scanf("%d%d", x + i, y + i);
tg[(x[i] + y[i]) & 1] = 1;
}
if(tg[0] & tg[1]) return puts("-1") & 0;
if(tg[0]) d[++ m] = 1;
for(int i = 30; ~ i; i --) d[++ m] = 1 << i;
printf("%d\n", m);
for(int i = 1; i <= m; i ++) printf("%d%c", d[i], " \n"[i == m]);
for(int i = 1; i <= n; i ++, putchar('\n')) {
for(int j = 1; j <= m; j ++) {
if(abs(x[i]) > abs(y[i])) {
if(x[i] > 0) x[i] -= d[j], putchar('R');
else x[i] += d[j], putchar('L');
} else {
if(y[i] > 0) y[i] -= d[j], putchar('U');
else y[i] += d[j], putchar('D');
}
}
}
return 0;
}
本文作者:hfhongzy
本文链接:https://www.cnblogs.com/hongzy/p/11519389.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步