uva 10881 Piotr's Ants (蚂蚁在一条线上行走 相遇转向的问题) (

/*
相遇转向问题,题意为 长度为L的木棍上 有n只蚂蚁,每只蚂蚁有一个初始运动方向,两只蚂蚁相遇后
立刻掉头。每秒走一个单位 求T秒后每只蚂蚁的顺序 要求按照输入时的顺序输出

我们这样想 当两只蚂蚁相遇后。如果忽略细节 其实可以认为是连个招呼都没打就对穿而过了
假如一只蚂蚁想右运动 如果和一只向左边走的蚂蚁相遇了,那么蚂蚁还是一左一右
所以说 对于每只蚂蚁 我们现在假设他就按照原来的情况走 那么得到的结果 如果不看编号的话是一样的

现在问题来了 就是编号问题。
比如 原来第一个输进来的那只蚂蚁 现在在哪儿呢?

我们发现 蚂蚁的相对位置是不可能改变的
也就是说 原来最左边的蚂蚁 之后肯定也还在最左边 当然或者是掉了
因为右边的任何一支蚂蚁想要到最左边蚂蚁的左边 必须是右边的往左 左边的往右 这样就一定会相遇
相遇就会掉头。。所以 蚂蚁的相对位置是不可能改变的
所以我们要对蚂蚁按照从做到右排序第 i 位的蚂蚁 最后还是在第 i位

这样计算好后 输入after数组
输出的顺序问题 就靠一个order数组 来解决
order[i]记录的是原来id是 i的 现在所在 在顺序序列 的第几位

*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const  int maxn=10000+10;//Ant's nubmer;
struct Ant
{
    int id;//输入数据中的顺序
    int pos;//范围为0-L
    int dir;//-1 向左 1 向右 0 turning

    bool operator < (const Ant & a1)const
    {
        return pos<a1.pos;
    }
};
Ant before[maxn];
int order[maxn];
char str[3][10]={"L","Turning","R"};

int main()
{
    int K,k;//case 'number;
    int T,L,n;//time long num;
    int i,j,p,d;
    scanf("%d",&K);
    char cdir;
    for(k=1;k<=K;++k)
    {
        scanf("%d %d %d",&L,&T,&n);
        for(i=0;i<n;++i)
        {
            scanf("%d %c",&p,&cdir);
            d= (cdir=='L' ? -1:1);
            before[i]=(Ant){i,p,d};//对于每只蚂蚁 before 存储初始状态
            //after[i]=(Ant){0,p+T*d,d};//after存最终状态,但是现在还不知道最终状态的蚂蚁标号
        }

        sort(before,before+n);//按照pos从左到右排序
        for(i=0;i<n;++i)
            order[before[i].id]=i;
        //order[i]就表示 id是 i的现在在排序后的序列是第几个

        for(i=0;i<n;++i)
        {
            before[i].pos+=before[i].dir*T;
        }
        sort(before,before+n);//T秒过后的所有蚂蚁的位置。
        for(i=0;i<n-1;++i)
        {
            if(before[i].pos==before[i+1].pos) before[i].dir=before[i+1].dir=0;
        }
        printf("Case #%d:\n",k);
        for(i=0;i<n;++i)
        {
            int a=order[i];
            if(before[a].pos<0 || before[a].pos>L)
                printf("Fell off\n");
            else
                printf("%d %s\n",before[a].pos,str[before[a].dir+1]);
        }
        printf("\n");
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值