翻译

[ABC289F] Teleporter Takahashi

首先,我们考虑一维问题:

  • 首先,高桥君位于数轴上的坐标位置s。我们希望通过重复操作“选择axb,将高桥君移动到与x对称的位置”将高桥君移动到t

当选择x进行操作时,位于点p的高桥君会移动到2xpx=(p+new)÷2)。由于p2xp(mod2),当st(mod2)时,无论如何都无法从s移动到t。以下假设st(mod2)

a=b时,只能移动到s2as。进行偶数次操作会将其移动到s,进行奇数次操作会将其移动到2as

ab时,按顺序操作aa+1会使pp+2。按顺序操作a+1a会使pp2。由于st(mod2),可以通过进行|st|次操作将高桥君从s移动到t


现在回到二维问题。需要满足sxtx(mod2)syty(mod2)

a=bc=d时,根据st的坐标确定操作次数为偶数次或奇数次。

  • a=btx{sx,2asx}时(即不管怎么变化横坐标都不行)
  • c=dty{sy,2csy}时(即不管怎么变化纵坐标都不行)
  • a=bc=dtx=sxty=2csy时(尽管二个都满足,但是它们并不是一个奇偶性所对应的)
  • a=bc=dtx=2asxty=sy时(尽管二个都满足,但是它们并不是一个奇偶性所对应的)

以上情况的答案为No

如果操作次数确定为偶数次或无法确定,那么x坐标要么已经匹配,要么相差2k(其中k0)。如果x坐标相差2k,则a<b。此时,可以按顺序操作(a,c)(a+1,c)(px,py)(px+2,py)。按顺序操作(a+1,c)(a,c)(px,py)(px2,py)。因此,可以通过进行|sxtx|次操作,保持高桥君所在位置的y坐标不变,将x坐标与sx匹配。

类似地,通过重复操作(a,c)(a,c+1)(a,c+1)(a,c),可以将高桥君所在位置的x坐标保持不变,将y坐标与sy匹配。

所需操作次数为|sxtx|+|sy+ty|4×105<106,非常小。

如果操作次数确定为奇数次(即不能只用偶数次,那么一定有一维被锁死),可以通过事先对某个点进行操作来将问题转化为偶数次操作的情况。(这样就可以将锁死的一维解放)例如,选择对(a,c)进行操作,则总操作次数为1+|(2asx)tx|+|(2csy)ty|1+8×105<106,问题得以解决。

总结如下:

  • 如果sxtxsyty的奇偶性不匹配,则答案为No
  • 如果满足以下情况之一,则答案为No
    • a=btx{sx,2asx}
    • c=dty{sy,2csy}
    • a=bc=dtx=sxty=2csy
    • a=bc=dtx=2asxty=sy
  • 否则,答案为Yes
  • 如果a=btx=2asx,或者c=dty=2csy,则进行操作(a,c)
  • 如果sxtx,则重复操作(a,c),(a+1,c)(a+1,c),(a,c)中合适的操作。
  • 如果syty,则重复操作(a,c),(a,c+1)(a,c+1),(a,c)中合适的操作。

以下是实现示例。在这类问题中,定义一个将操作和输出结合在一起的函数可能会使代码更易于实现。

(附加:可以找到最短的操作序列。)

#include <iostream>

int main() {
	using namespace std;

	long sx, sy, tx, ty, a, b, c, d;
	cin >> sx >> sy >> tx >> ty >> a >> b >> c >> d;

	// 如果坐标的奇偶性不匹配,则输出 No
	if ((sx ^ tx) % 2 != 0 || (sy ^ ty) % 2 != 0) {
		cout << "No" << endl;
		return 0;
	}

	// 可能性_0:能否通过偶数次操作到达
	// 可能性_1:能否通过奇数次操作到达
	bool 可能性_0{(a != b || sx == tx) && (c != d || sy == ty)};
	bool 可能性_1{(a != b || sx + tx == a + b) && (c != d || sy + ty == c + d)};

	// 如果两者都不可能,则输出 No
	if (!可能性_0 && !可能性_1) {
		cout << "No" << endl;
		return 0;
	}

	// 否则,输出 Yes
	cout << "Yes" << endl;

	// 定义操作函数
	const auto 操作{[&sx, &sy](long x, long y){
		cout << x << " " << y << endl;
		sx = 2 * x - sx;
		sy = 2 * y - sy;
	}};

	// 如果无法通过偶数次操作,则先进行一次操作
	if (!可能性_0) 操作(a, c);

	// 逐步调整坐标,使其相差为2的倍数
	while (sx < tx) { // 增加 x 坐标
		操作(a, c);
		操作(a + 1, c);
	}
	while (sx > tx) { // 减少 x 坐标
		操作(a + 1, c);
		操作(a, c);
	}
	while (sy < ty) { // 增加 y 坐标
		操作(a, c);
		操作(a, c + 1);
	}
	while (sy > ty) { // 减少 y 坐标
		操作(a, c + 1);
		操作(a, c);
	}

	return 0;
}

本文作者:wscqwq

本文链接:https://www.cnblogs.com/wscqwq/p/17687451.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   wscqwq  阅读(5)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起