1. 程式人生 > 實用技巧 >[思維構造] 題解 Robot Arms

[思維構造] 題解 Robot Arms

[思維構造] 題解 Robot Arms

題目連結

題目分析

好吧,這道題目按理來說應該是套路題,但是我就是不會,所以寫篇題解學習一下。

首先如果 \(X_i+Y_i\) 的奇偶性不同就無解,因為每次操作後 \(X_i+Y_i\) 的奇偶性都是固定的,不肯能出現奇偶性不同的情況。

如果 \(X_i+Y_i\) 的奇偶性全部相同,那麼必定有解,當 \(X_i+Y_i\) 為偶數的時候可以通過一次走動變成奇數,所以只考慮 \(X_i+Y_i\) 為奇數的情況。

可以使用二進位制來構造,通過序列 \(1,2,4,8,16,\dots,2^k\) 可以從 \((0,0)\) 走到任意一個滿足 \(\mbox{abs}(x)+\mbox{abs}(y)<2^{k+1}\)

並且 \(x+y\) 為奇數的位置 \((x,y)\) ,可以使用歸納法來證明。

\(k=0\) 時,顯然序列 \(1\) 可以到達 \((1,0),(0,1),(-1,0),(0,-1)\)

假設 \(1,2,4,\dots,2^{k-1}\) 滿足該條件,然後我們新加入了一個數 \(2^k\) ,如果 \((x,y)\) 滿足 \(\mbox{abs}(x)+\mbox{abs}(y)<2^{k+1}\) 並且 \(x+y\) 為奇數,那麼 \(\mbox{abs}(x)\)\(\mbox{abs}(y)\) 中最多隻有一個數的二進位制第 \(k\) 位為 \(1\) ,不妨假設 \(\mbox{abs}(x)>\mbox{abs}(y)\)

(需要注意 \(\mbox{abs}(x)\ne \mbox{abs}(y)\) ,否則不滿足 \(\mbox{abs}(x)+\mbox{abs}(y)\) 是奇數),如果 \(\mbox{abs}(x)\ge 2^k\) ,那麼我們可以令 \(\mbox{abs}(x)\) 變成 \(\mbox{abs}(x)-2^k\) ,仍然滿足條件,否則我們可以令 \(\mbox{abs}(x)\) 變成 \(2^k-\mbox{abs}(x)\) ,則 \(2^k-\mbox{abs}(x)+\mbox{abs}(y)<2^k\) ,仍然滿足條件。

當然也可以通過圖來理解,每次序列增加一個數相當於是覆蓋的點向上向下向左向右並起來的所有點:

不難發現,從 \((0,0)\) 通過序列 \(1,2,4,8,\dots,2^k\) 只有唯一的方法走到 \((x,y)\) ,直接遞迴求解即可。

參考程式碼

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ch() getchar()
#define pc(x) putchar(x)
using namespace std;
template<typename T>void read(T&x){
	static char c;static int f;
	for(c=ch(),f=1;c<'0'||c>'9';c=ch())if(c=='-')f=-f;
	for(x=0;c>='0'&&c<='9';c=ch())x=x*10+(c&15);x*=f;
}
template<typename T>void write(T x){
	static char q[65];int cnt=0;
	if(x<0)pc('-'),x=-x;
	q[++cnt]=x%10,x/=10;
	while(x)
		q[++cnt]=x%10,x/=10;
	while(cnt)pc(q[cnt--]+'0');
}
const int maxn=1005,Base=38;
long long _[Base];
long long ABS(long long x){
	return x<0?-x:x;
}
int judge(long long x,long long y,int sp){
	return ABS(x)+ABS(y)<_[sp+1];
}
void solve(long long x,long long y,int sp){
	if(~sp){
		if(judge(x-_[sp],y,sp-1)){solve(x-_[sp],y,sp-1);pc('R');}
		if(judge(x+_[sp],y,sp-1)){solve(x+_[sp],y,sp-1);pc('L');}
		if(judge(x,y-_[sp],sp-1)){solve(x,y-_[sp],sp-1);pc('U');}
		if(judge(x,y+_[sp],sp-1)){solve(x,y+_[sp],sp-1);pc('D');}
	}
}
long long X[maxn],Y[maxn];
int main(){
	int n,s=0,ok=true;read(n);
	for(int i=1;i<=n;++i){
		read(X[i]),read(Y[i]);
		if(i==1)s=(X[i]+Y[i])&1;
		else ok&=(s==((X[i]+Y[i])&1));
	}
	if(!ok)puts("-1");
	else{
		_[0]=1;
		for(int i=1;i<Base;++i)
			_[i]=_[i-1]<<1;
		if(s&1)write(Base),pc('\n');
		else   write(Base+1),pc('\n'),write(1),pc(' ');
		for(int i=0;i<Base;++i)write(_[i]),pc(" \n"[i==Base-1]);
		for(int i=1;i<=n;++i){
			if(!((X[i]+Y[i])&1))pc('L'),++X[i];
			solve(X[i],Y[i],Base-1);pc('\n');
		}
	}
	return 0;
}