坠落的蚂蚁(模拟)

题意

一根长度为\(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;
}
posted @ 2022-08-09 19:13  pbc的成长之路  阅读(50)  评论(0编辑  收藏  举报