【思维】Hzy's Rabbit Stick

题目描述

给兔兔们染完颜色后,Hzy把n只颜色不同的兔兔放在了一根长度为L=10n的木棍的不同位置(每只兔兔的位置在[0,L]之间)上,让她们做做运动。

在最开始的时候,Hzy会给每只兔兔指定一个方向,所有的兔兔都会乖乖地按照Hzy给她们指定的方向走(速度为每秒一个单位长度)。而当两只兔兔相遇(到达相同的位置)时,它们会同时掉头(掉头的时间忽略不计),下一秒她们会朝着相反的方向走。如果某只兔兔走到了木棍的边缘(位置0或者位置L),则她也会掉头,下一秒她会朝着相反的方向走。

现在,兔兔们想知道,T秒后她们分别在什么位置。

 

输入

第一行两个整数n、T,分别表示兔兔的数量和运动的秒数。
之后的n行,每行两个整数,依次表示从左到右每只兔兔的位置和朝向(−1表示向左,1表示向右)。

 

输出

输出n行,依次表示每只兔兔(与输入中的顺序对应)的位置。

 

样例输入

 

3 2
1 -1
5 1
9 -1

样例输出

1
7
7

 

提示

对于100%的数据,1≤n≤105,0≤T≤1018,兔兔的起始位置均为奇数。


【小结】:

看完题目,我第一感觉就认为这个题目好像在哪里做过一样。

没错,我想到的就是poj 1852

这个题目有点神似,因为问题都是相遇之后折返走,然后poj 1852 .

这题的做法,直接就是把两只蚂蚁折返走,看作两只蚂蚁互相穿过去。

这题的答案就浮现出来了。

 

这是第一个想法,然后麻烦的问题又来了,它说要输出小兔子最后所在的位置。

是按输入的顺序来输出。

问题是:蚂蚁这个题目,只能是看作穿过去罢了,但是两只蚂蚁的身份明显就交换了,

而且t给的很大,无法枚举跟踪每只蚂蚁的行踪。

所以,这时候引入第二个概念。

我初中做到一个期末考试的数学题。

我已经找不到原题给大家了,

然后这个题目的意思是,两球相遇,然后一个球以匀速前进,然后另外一个球相遇后折返。

问:另外一个球移动的距离。

当时我真的不会做这个题,后来想想,也就那么简单,

大家思考一下,其实即使两只蚂蚁身份改变了,但是相对来说,其实每一只蚂蚁都在自己所在的区域下运动。

所以肯定答案只要把所有位置求出,最后排序即可。

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+10;
typedef struct Node{
    int No,x,flag;
    /*bool operator < (const Node &p)const {
        return x<p.x;
    }*/
}Node;
Node a[N];
bool cmp(Node a,Node b){
    return a.x<b.x;
}
int main()
{
    int n,L,t;
    ll tt;
    //freopen("stick.in", "r", stdin); freopen("stick.out", "w", stdout);
    scanf("%d%lld",&n,&tt);
    L=10*n;
    t=(int)(tt%((ll)(2*L)));
    for(int i=0;i<n;i++){
        scanf("%d%d",&a[i].x,&a[i].flag);
        a[i].No=i;
    }
    for(int i=0;i<n;i++){
             
        if(a[i].flag==-1){
            if(a[i].x>=t){
                a[i].x=a[i].x-t;
            }else if(a[i].x<t&&t<a[i].x+L){
                a[i].x=t-a[i].x;
            }else{
                a[i].x=2*L-t+a[i].x;
            }
        }
        else if(a[i].flag==1){
            if(t+a[i].x<=L){
                a[i].x=t+a[i].x;
            }else if(L<t+a[i].x&&t+a[i].x<=2*L){
                a[i].x=2*L-t-a[i].x;
            }else if(t+a[i].x>2*L){
                a[i].x=(t+a[i].x)%(2*L);
            }
        }
    }
    sort(a,a+n,cmp);
    for(int i=0;i<n;i++){
        printf("%lld\n",a[i].x);
    }
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值