拼图 |两个带降落伞的机器人在一条线上
问题
两个机器人带着降落伞降落在无限的一维数轴上。他们都在着陆后立即释放降落伞并开始移动。他们只能使用以下功能。
I. moveLeft() // 机器人在 1 单位时间内向左移动 1 个单位
二、 moveRight() // 机器人在 1 单位时间内向右移动 1 个单位
三、 noOperation() // 机器人不移动,需要 1 个单位时间
四、 onTopOfParachute() // 如果机器人站在任何一个降落伞的顶部,则返回 true,否则返回 false
V. didWeMeet() // 如果机器人遇到另一个机器人,则返回真,否则返回假
编写一个函数,使机器人彼此相遇。机器人将执行此函数的相同副本。
解决方案:
方法一:
将两个机器人向相反方向移动,并在每一步检查它们是否相遇。
但这行不通。考虑机器人 1 在位置 0 和机器人 2 在位置 100。如果机器人 1 向右移动,机器人 2 向左移动,它们将在位置 50 相遇。但如果机器人 1 向左移动而机器人 2 向右移动,他们永远不会见面。因为我们没有任何方法可以找出机器人的坐标。这种方法行不通。
方法二:
向左移动两个机器人。如果机器人穿过降落伞。反转第二个机器人的方向并继续沿相同方向移动第一个机器人。
但这行不通。因为两个机器人都执行各自程序的单独副本。一个程序只能影响执行该程序的机器人,而不能影响另一个机器人,因为它是由同一程序的副本单独执行的。并且它的运动是由那个程序控制的,一个变量分配在另一个程序中将不起作用,即不能从这个机器人执行的程序中改变其他机器人的方向。
方法三:
按照这个模式 moveLeft() 1 次,moveRight() 2 次,moveLeft() 3 次等等。在每次迭代中,机器人都会越过自己的降落伞一次。但是经过一段时间后,一个机器人会越过自己的降落伞,也会越过另一个机器人的降落伞。此时,它已经与另一个机器人相遇了。
方法四:
无论机器人是否已到达其他人的降落伞,请保留一个标志。如果已到达,则调用 moveLeft() 两次,否则调用 moveLeft() 和 noOperation()。这样,一个机器人一到达另一个机器人的降落伞,它的速度就会加倍,最终他们会相遇。
注意:不要从着陆点开始以两倍于其他机器人的速度移动机器人。因为我们没有任何信息哪个机器人在后面,哪个机器人在前面。因此,如果前面的机器人以两倍于落后机器人的速度移动,那么它将永远无法抓住它,因此永远不会相遇。
伪代码:
void roboMeet()
{
// set flag as false.
bool reachedParachute = false;
// Till both robots meet
while( !didWeMeet() )
{
// If flag is set, move left twice.
if(reachedParachute)
{
moveLeft();
moveLeft();
}
// Else walk left for 1 unit of time
// and stop for 1 unit.
else
{
moveLeft();
noOperation();
}
// If reach on top of parachute, set flag as true.
if( onTopOfParachute() )
{
reachedParachute = true;
}
}
}