把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

【AT4432】[ARC103B] Robot Arms(构造)

点此看题面

  • 给定\(n\)个点坐标\((x_i,y_i)\)
  • 要求构造一个长度为\(m\)的数组\(c_{1\sim m}\),第\(i\)步选择向上下左右的某个方向走\(c_i\)个单位长度,并对于每个点给出一种走到对应坐标的走法。
  • \(n\le10^3,x_i,y_i\le10^9\),要求\(m\le40,c_i\le10^{12}\)

二进制分解

首先判无解是非常好判的,只要判断\(x_i+y_i\)的奇偶性是否全部相同即可。

然后考虑构造,初步想法就是对于两维分别二进制分解,但这样的\(m\)就会达到\(2\times 31\)

可实际上,我们只要用一组\(2^{30},2^{29},...,2^0\),并在\(x_i+y_i\)为偶数的时候额外添上一个\(2^0\)就可以构造出答案了。

具体方案就是枚举每个数,每次给\(|x_i|,|y_i|\)中绝对值较大的那位加/减上这个数的值。

自己画一下应该容易证明正确性。

代码:\(O(32n)\)

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 1000
using namespace std;
int n,x[N+5],y[N+5],a[40];
int main()
{
	RI i,j,c[2]={0,0};for(scanf("%d",&n),i=1;i<=n;++i) scanf("%d%d",x+i,y+i),c[(x[i]+y[i])&1]=1;//记录奇偶性是否都存在
	RI t=0;if(c[0]&&c[1]) return puts("-1"),0;for(i=30;~i;--i) a[++t]=1<<i;c[0]&&(a[++t]=1);//如果两种都存在则无解,否则构造一组2的幂次
	for(printf("%d\n",t),i=1;i<=t;++i) printf("%d%c",a[i]," \n"[i==t]);
	for(i=1;i<=n;putchar('\n'),++i) for(j=1;j<=t;++j)
		abs(x[i])>abs(y[i])?(x[i]<0?(putchar('L'),x[i]+=a[j]):(putchar('R'),x[i]-=a[j]))//每次给绝对值大的数加或减当前值
		:(y[i]<0?(putchar('D'),y[i]+=a[j]):(putchar('U'),y[i]-=a[j]));//接上
	return 0;
}
posted @ 2021-04-06 21:08  TheLostWeak  阅读(76)  评论(0编辑  收藏  举报