AtCoder Regular Contest 103 D. Robot Arms

链接:https://arc103.contest.atcoder.jp/tasks/arc103_b

题意:

给n个点,坐标范围1e9, 让你构造出m条边,(m <= 40)每条边可以有上下左右四个方向,长度 < 1e12,目的是这m条边可以达到任意一个点(respectively),问能不能构造出来,能就输出,不能输出-1.

解题思路:

首先容易想到输出-1的情况,每个点横纵坐标相加的奇偶性得是一样的,不然构造不出来

能构造出来的情况:

不妨假设坐标和为奇数

选出这些边:{1, 2, 4, 8, ... , 2 ^ k },先考虑只有1的情况,可到达点(0, 1), (1, 0), (0, -1), (-1, 0),加上2,可加上到达(0, 3), (0, -3), (3, 0), (-3, 0), (2, 1), (1, 2), (-1, 2), (-2, 1), (-2, -1), (-1, -2), (1, -2), (2, -1),画出来,发现是顶点为(3, 0), (-3, 0), (0, 3), (0, -3)的正方形上的所有整点。

By induction, 有了这些点,可以到达顶点为(2^(k+1)−1,0),(−2^(k+1)+1,0),(0,2^(k+1)−1),(0,−2(^k+1)+1)上的所有整点。

刚刚假设了坐标和为奇数,对于偶数,只需要加一个边长为1的边即可。

然后贪心边长从长到短来安排方向即可

Ac Code:

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define fi first
#define se second
#define pb push_back
#define lowbit(x) x&(-x)
#define PII  pair 
#define all(x) x.begin(), x.end()
#define FAST ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
typedef long long ll;
const ll inf = 1e18;
const int mod = (int)1e9 + 7;
const int maxn = (int)1e3 + 5;
using namespace std;
 
#define int ll
 
struct node{
	int x, y;
}a[maxn];
 
int d[50];
int dir[4][2] = { {-1, 0}, {1, 0}, {0, 1}, {0, -1} };
string s = "LRUD";
int n, cnt = 0;
 
int dis(int x1, int y1, int x2, int y2){
	return abs(x1 - x2) + abs(y1 - y2);
}
 
void work(int x, int y){
	node now;
	now.x = now.y = 0;
	for(int i = 1; i <= cnt; i++){
		int Min = inf;
		int pos = 0;
		for(int j = 0; j < 4; j++){
			int tx = now.x + dir[j][0] * d[i], ty = now.y + dir[j][1] * d[i];
			int t = dis(tx, ty, x, y);
			if(Min > t) Min = t, pos = j;
		}
		now.x += d[i] * dir[pos][0], now.y += d[i] * dir[pos][1];
		putchar(s[pos]);
	}
	puts("");
}
 
int32_t main()
{
	scanf("%lld", &n);
	for(int i = 1; i <= n; i++){
		scanf("%lld %lld", &a[i].x, &a[i].y);
		if((abs(a[i].x + a[i].y) & 1) != (abs(a[1].x + a[1].y) & 1)) return 0 * puts("-1");
	}
	for(int i = 30; i >= 0; i--){
		d[++cnt] = 1 << i;
	}
	if((a[1].x + a[1].y) % 2 == 0) d[++cnt] = 1;
	printf("%lld\n", cnt);
	for(int i = 1; i < cnt; i++)
		printf("%lld ", d[i]);
	printf("%lld\n", d[cnt]);
	for(int i = 1; i <= n; i++){
		work(a[i].x, a[i].y);
	}
	return 0;
}

over

你可能感兴趣的:(Atcoder)