UVa 1622 机器人(robot)

博客探讨了在r * c网格中,如何通过n, s, w, e指令移动机器人以最大化指令执行次数。首先分析了n >= s, w >= e的情况,说明了在r > c时上下移动的优势。接着,当s = 0时,通过贪心策略判断上下或左右移动的最优选择。最后,考虑到特殊情况,需要再次检查以左右移动为优先的情况。给出了相关代码实现。" 135443931,5632965,华为OD机考C卷:API集群负载统计C++解决方案,"['C++', '华为OD', '算法', '数据结构', '编程挑战']

题意:
给定一个r * c的网格 (1 <= r , c <= 1e5) ,在这个网格里面均分 1 * 1的小格子, 每个格子初始都有一个机器人,你可以执行n, s, w, e指令,让所有机器人分别向上向下向左向右移动,出边界的机器人会爆炸,以后再也不会听从指令,求最大指令数。这里可能没有描述清楚
我们以一个样例为解答

例如 2 2 1 1 1 1
代表有2 * 2 的网格 有四个机器人 每个方向分别有1条指令
最优解是

  • 先向上 这样有4个机器人执行指令
  • 再向下 这样有2个机器人执行指令
  • 再向左 这样有2个机器人执行指令
  • 再向右 这样有1个机器人执行指令

所以答案为9
解决了题目的意思后,我们分析一下题目

分析:
Step1
这一步相信大家最容易想到,我们以n >= s w>= e这种情况讨论,要是不是可以交换两个元素的值,因为上下交换并不影响最后的结果
这个时候如果r > c 那么疯狂上下摇摆到 s = 0时是最优的,这里要考虑 n >= s + 1的这种情况,在这种情况下可以加上 x * y
我作了一幅图,方便读者理解。

在这里插入图片描述
解决完这个问题后

进入 Step2
这个时候s = 0了 但是不确定左右这样循环移动(如果 w 和 e 都大于0的情况)还是继续向上移动好,这个时候就要贪心,判断每一步的利益得失。

具体在代码里是 c * 1 - r * 1 + (c - 1) * e <= 0
这里特定写出了 * 1方便读者理解意思

这个关系式从左到右的解读分别是
c * 1 =>: 本次上下走,如果将来左右走,将会永久损失一行的robot可以接受指令数
r * 1 => 本次上下走,如果将来上下走,将会永久损失一列的robot可以接受的指令数
(c - 1) * e => 本次上下走,如果将来左右走,还会永久损失 ( c - 1) * e 的指令数
这个关系式之所以是while 是因为他是对于每一步的下一步而言的,而且这下一步的损失是永久的
这里可能不好理解,就是这个关系式,是基于当前情况的最优,当时当 r 和 n 更新后,不一定为最优了
这里如果读者不理解的,可以评论。

Step3
这个时候 s = 0 e = 0 那么只要单独考虑 r 和 c 和 n 和 w是否还能走就行了,这个应该也比较好考虑,读者应该也比较好理解。
就不做详细阐述了。

细心的读者可能发现了,这样的话,我们是假定一开始上下摇摆来的更好,可是实际上并不是,例如一个很简单的例子,一个1 * 10的网格,假设可以无限次的左右摇摆,但是你一开始就上下摇摆了,之后左右摇摆就都是0了,考虑到这种情况,所以应该再做一遍,这一边就是以左右摇摆为先了。

代码如下:

#include<bits/stdc++.h>
#define LL long long
#define ms(s) memset(s, 0, sizeof(s))
using namespace std;

LL solve(LL r, LL c, LL n, LL s, LL w, LL e) {
   
   
    if(n < s) swap(
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值