“坠落的蚂蚁”思路

坠落的蚂蚁

https://www.nowcoder.com/practice/fdd6698014c340178a8b1f28ea5fadf8?tpId=40&tqId=21420&tPage=1&rp=1&ru=/ta/kaoyan&qru=/ta/kaoyan/question-ranking

关于“坠落的蚂蚁”这道题。一开始我尝试用追踪记录每一只蚂蚁的状态的方法解题,代码写了很长,最后只有40%的用例通过了检验,折腾了半天我也没发现到底错误在什么地方。代码:https://paste.ubuntu.com/p/q3GCtB2fw4/

这道题的一种简单思路如下:
1.静止蚂蚁的位置是固定不变的,即使蚂蚁相遇并发生了速度交换,永远都有一只蚂蚁处在初始静止蚂蚁A的位置。
2.假设A左侧蚂蚁都是向左的,右侧蚂蚁都是向右的,那么A必定不动,无法坠落。
3.左右移动的蚂蚁相遇时会交换速度,但从A的视角来看,是否交换速度对A的移动来说没有任何影响,可以看做两只蚂蚁互不影响继续前进。
4.综合2、3两点可以看出只有A左侧向右移动的蚂蚁和A右侧向左移动的蚂蚁会对A的移动产生影响。
5.当A左侧向右移动的蚂蚁和A右侧向左移动的蚂蚁数量相等时,A必定无法掉落。因为当A与距离其最近的LR(左侧向右)蚂蚁和RL(右侧向左)蚂蚁相遇之后,一定会回到静止状态。
6.当LR和RL蚂蚁不一样多时,A最终会继承较多一侧某蚂蚁的速度并且坠落,坠落时间等于该蚂蚁不受任何影响直线前进直至坠落的时间。
7.确定6中所指蚂蚁的方法,以LR蚂蚁较多为例:设RL蚂蚁数量为n,在LR蚂蚁中按初始位置从高到低数起,第n+1个LR蚂蚁即为所求蚂蚁。

启发:
当最终结果只关心某个元素时,可以考虑模糊其他元素的身份区别,只关心他们对所求元素的影响,将这种影响抽象出来作为解题思路可以大大降低编程难度。
追踪记录每个元素的方式不是不能用,在难以抽象的复杂情况下甚至可能会有更好的效果。但其缺点也很明显:当元素数量很多过程很长的时候,几乎不能用调试的方法找到其中细小的逻辑错误。这也是最终我只有40%通过率的原因。

代码:

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>

using namespace std;

struct ant{
    int location;
    int velocity;
};

bool Comp(ant a, ant b) {
    return a.location < b.location;
}

int main() {
    int n;
    while (scanf("%d", &n) != EOF) {
        ant Ants[n];
        int Apos;
        for (int i = 0; i < n; i++) {
            scanf("%d %d", &Ants[i].location, &Ants[i].velocity);
            if (Ants[i].velocity == 0) {
                Apos = Ants[i].location;
            }
        }        //输入结构体数组,记录A蚂蚁初始位置
        vector<int>left, right;        //定义两个容器分别存放A左侧向右蚂蚁,A右侧向左蚂蚁
        sort(Ants, Ants + n, Comp);
        for (int i = 0; i < n; i++) {
            if (Ants[i].location < Apos && Ants[i].velocity == 1) {
                left.push_back(Ants[i].location);
            }
            if (Ants[i].location > Apos && Ants[i].velocity == -1) {
                right.push_back(Ants[i].location);
            }
        }        //将LR和RL元素的位置加入容器中
        if (left.size() == right.size()) {
            printf("Cannot fall!");
        }
        else if (left.size() > right.size()) {
            printf("%d", 100 - left[left.size() - right.size() - 1]);
        }
        else {
            printf("%d", right[left.size()]);
        }
    }
}
全部评论
看完。老哥分析得很棒
点赞 回复 分享
发布于 2021-01-27 19:38
这位老铁写得很仔细
点赞 回复 分享
发布于 2021-02-08 20:35
正解、 模拟坑太多了, 根本解不出来。
点赞 回复 分享
发布于 2022-02-28 20:49
点赞 回复 分享
发布于 2022-03-23 16:45

相关推荐

11-27 17:35
已编辑
蚌埠坦克学院 C++
深信服 后台开发 n×12
点赞 评论 收藏
分享
粗心的雪碧不放弃:纯学历问题,我这几个月也是一直优化自己的简历,后来发现优化到我自己都觉得牛逼的时候,发现面试数量也没有提升,真就纯学历问题
点赞 评论 收藏
分享
点赞 评论 收藏
分享
美团 后端开发 总包n(15%是股票)
点赞 评论 收藏
分享
评论
31
2
分享
牛客网
牛客企业服务