• 坠落的蚂蚁(模拟)


    题意

    一根长度为\(1\)米的木棒上有\(N\)只蚂蚁在爬动。

    它们的速度为每秒一厘米或静止不动,方向只有两种,向左或者向右。

    如果两只蚂蚁碰头,则它们立即交换速度并继续爬动。

    三只蚂蚁碰头,则两边的蚂蚁交换速度,中间的蚂蚁仍然静止。

    如果它们爬到了木棒的边缘(\(0\)\(100\) 厘米处)则会从木棒上坠落下去。

    在某一时刻蚂蚁的位置各不相同且均在整数厘米处(即\(1, 2, 3, \dots, 99\)厘米),有且只有一只蚂蚁\(A\)速度为\(0\),其他蚂蚁均在向左或向右爬动。

    给出该时刻木棒上的所有蚂蚁位置和初始速度,找出蚂蚁\(A\)从此时刻到坠落所需要的时间。

    题目链接:https://www.acwing.com/problem/content/3477/

    数据范围

    \(2 \leq N \leq 99\)

    思路

    首先分析一条性质:对于除\(A\)外的其他蚂蚁,如果两只蚂蚁碰头,那么相当于什么都没有发生。因为除了\(A\)之外,其他蚂蚁的编号是无所谓的,两者交换速度就相当于对穿了。

    通过这条性质,我们发现,如果\(A\)左边的蚂蚁向左走,或者\(A\)右边的蚂蚁向右走,那么它们是不会影响\(A\)的。

    然后再分析一条性质,如果\(A\)左边和右边各有一只蚂蚁,且左边的蚂蚁向右走,右边的蚂蚁向左走,那么\(A\)最终位置不变。我们不妨设右边的蚂蚁距离\(A\)更近,首先\(A\)与右边的蚂蚁碰头,\(A\)向左走,右边的蚂蚁停留在了\(A\)的位置;然后\(A\)与左边的蚂蚁碰头,左边的蚂蚁向左走,\(A\)向右走;最后\(A\)与右边的蚂蚁碰头,右边的蚂蚁向右走,\(A\)停留在了最初的位置。此时,左边的蚂蚁向左走,右边的蚂蚁向右走,它们再也不会影响\(A\)了。因此,在该情况下,\(A\)停留在原来的位置上。

    下面再来一条推论,如果左边向右走的蚂蚁数量与右边向左走的蚂蚁数量相同,则\(A\)最终位置不变。首先\(A\)与左边、右边距离\(A\)最近的相碰,停留在原处;然后再与左右第\(2\)近的蚂蚁相碰,停留在原处。以此类推,最终\(A\)依然停留在原处。

    如果两边的蚂蚁数量不同,不妨设左边向右走的蚂蚁更多。根据上面那条推论,我们可以“消掉”右边全部的蚂蚁以及左边相同数量的蚂蚁(按照从近到远的顺序)。消除过后,左边距离\(A\)最近的蚂蚁会与\(A\)进行碰头,\(A\)继承了左边蚂蚁的速度继续向右走。相当于,最终的时间就是“消除”后,左边最近蚂蚁走到右端点的时间,也就是左边最近蚂蚁到右端点的距离。

    因此,做法如下:先对蚂蚁按照位置进行排序。用两个vector分别存储左边向右走的蚂蚁和右边向左走的蚂蚁(按照位置从小到大)。如果两边数量相等,则\(A\)不会掉下去。如果左边蚂蚁多,设右边蚂蚁数量为\(r\),那么就看左边倒数第\(r+1\)只蚂蚁的位置。如果右边蚂蚁多,设左边蚂蚁数量为\(l\),那么就看右边第\(l+1\)只蚂蚁的位置。

    代码

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <vector>
    
    using namespace std;
    
    typedef pair<int, int> pii;
    
    int n;
    vector<pii> a;
    vector<int> l, r;
    
    int main()
    {
        scanf("%d", &n);
        int A;
        for(int i = 1; i <= n; i ++) {
            int x, y;
            scanf("%d%d", &x, &y);
            if(!y) A = x;
            a.push_back({x, y});
        }
        sort(a.begin(), a.end());
        for(auto p : a) {
            int x = p.first, y = p.second;
            if(!y || x < A && y < 0 || x > A && y > 0) continue;
            if(x < A) l.push_back(x);
            else r.push_back(x);
        }
        if(l.size() == r.size()) printf("Cannot fall!\n");
        else if(l.size() > r.size()) printf("%d\n", 100 - l[l.size() - 1 - r.size()]);
        else printf("%d\n", r[l.size()]);
        return 0;
    }
    
  • 相关阅读:
    java基础知识——7.断点调试与数据加密
    Hibernate最基础配置的记忆方式
    Redis集群命令
    VMware Workstation下centos的使用
    Redis入门
    Shell脚本
    使用Java遇到的问题
    使用Linux
    压缩包安装MySQL服务
    安装windows+ubuntu双系统
  • 原文地址:https://www.cnblogs.com/miraclepbc/p/16567301.html
Copyright © 2020-2023  润新知