- 给定(n)个点坐标((x_i,y_i))。
- 要求构造一个长度为(m)的数组(c_{1sim m}),第(i)步选择向上下左右的某个方向走(c_i)个单位长度,并对于每个点给出一种走到对应坐标的走法。
- (nle10^3,x_i,y_ile10^9),要求(mle40,c_ile10^{12})
二进制分解
首先判无解是非常好判的,只要判断(x_i+y_i)的奇偶性是否全部相同即可。
然后考虑构造,初步想法就是对于两维分别二进制分解,但这样的(m)就会达到(2 imes 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
",t),i=1;i<=t;++i) printf("%d%c",a[i],"
"[i==t]);
for(i=1;i<=n;putchar('
'),++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;
}