UVa 10881 - Piotr's Ants(精巧)

44 篇文章 0 订阅

题目链接

简介:
蚂蚁们在树枝上的运动

分析:
假如我们离远一点,看这些蚂蚁会是什么样呢
一群密密麻麻的小黑点在移动,由于黑点太小,而且移动速度都相等,
所以当蚂蚁因碰撞而掉头时,看上去和两个点对穿而过没有什么区别
换句话说,如果把蚂蚁看做没有区别的小黑点,那么只要独立计算每只蚂蚁在T时刻的位置即可

比如,有3只蚂蚁:(3,R),(4,L),(6,L)
则两秒之后三只蚂蚁分别为:(5,R),(2,L),(4,L)

现在我们已经得到答案了,但是还有一个problem
在实际问题中,两只蚂蚁是不会对穿的,
也就是说,蚂蚁1的初始位置是(3,R),一定有一只蚂蚁的最终位置是(5,R),但是不一定是蚂蚁1,
所以我们现在的问题是把坐标的蚂蚁对上号,弄清楚“谁是谁”

我们观察一下蚂蚁们行进的路线,
不会对穿是一个很重要的信息,也就是说,ta们只能在一个没有其他蚂蚁的区间内运动,是不会越过任何蚂蚁的
换句话说:

ta们的相对位置是不会变的

因此把所有目标位置从小到大排序,则从左到右的每个位置对应了初始状态下从左到右的每只蚂蚁

由于一开始给出的蚂蚁可能是无序的
所以我们还需要处理一下每只蚂蚁的排名

tip

在算出最终坐标之后,如果发现两个相邻蚂蚁的坐标相等,那么说明ta们正在转身
小于0大于L才视为掉下木棍

我就因为少输出了一行空行,就PE了
真的搞不懂外国佬为什么老是本末倒置

//这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

const int N=10003;
int n,l,t;
struct Ant{
    int id;
    int p;
    int d;     //-1 left 0 turning 1 right
};
Ant before[N],after[N];
int wz[N];

int cmp(const Ant &a,const Ant &b)
{
    return a.p<b.p;
}

int main()
{
    int T;
    scanf("%d",&T);
    for (int cas=1;cas<=T;cas++)
    {
        scanf("%d%d%d",&l,&t,&n);
        for (int i=1;i<=n;i++)
        {
            scanf("%d",&before[i].p);
            char ch[2];
            scanf("%s",&ch);
            if (ch[0]=='R') before[i].d=1;
            else before[i].d=-1;
            before[i].id=i;
        }
        sort(before+1,before+n+1,cmp);

        for (int i=1;i<=n;i++)
        {
            after[i]=before[i];
            if (after[i].d==1)
                after[i].p+=t;
            else after[i].p-=t;
            wz[before[i].id]=i;               //第i个输入的蚂蚁实际上排第wz[i]个 
        }

        sort(after+1,after+1+n,cmp);
        for (int i=1;i<n;i++) 
            if (after[i].p==after[i+1].p) after[i].d=after[i+1].d=0;

        printf("Case #%d:\n",cas);
        for (int i=1;i<=n;i++)
        {
            int r=wz[i];
            if (after[r].p>l||after[r].p<0) printf("Fell off\n");
            else 
            {
                printf("%d ",after[r].p);
                if (after[r].d==-1) printf("L\n");
                else if (after[r].d==1) printf("R\n");
                else printf("Turning\n");
            }
        }

        puts("");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值