Linear world POJ - 2674(弹性碰撞+技巧)

题意:

给你n个居民的起始位置,各自在长度为l的平台,以同样的速度向左或向右走,当碰见时往相反方向走,问最后掉下去的居民花费的时间以及姓名。

题目:

The Disc, being flat, has no real horizon. Any adventurous sailors who get funny ideas from staring at eggs and oranges for too long and set out for the antipodes soon learned that the reason why distant ships sometimes looked as though they were disappearing over the edge of the world was that they were disappearing over the edge of the world. (Terry Pratchett -Colour of Magic)
Not so long time ago people used to believe that they live on 2-D world and if they will travel long enough in one direction, they will fall down over the edge. Even when it was proved that the Earth is rounded some of them were still afraid to travel to the southern hemisphere.
Try to imagine one 1-D (linear) world. On such world there are only two possible directions (left and right). All inhabitants of such world were created exactly at the same time and suddenly all of them start to move (all with same constant velocity) in one or the other direction. If two inhabitants encounter each other, they politely exchange greetings and then they turn around and start to move in an opposite direction. When an inhabitant reaches the end of the world he falls away and disappears.
Your task is to determine, for a given scenario of creation, which inhabitant and when (counting from the moment of creation) will be the last one to fall away. You can assume that the time required to exchange greetings and turn around is 0.

Input

The input consists of multiple descriptions (data sets) of the creation moment. File structure is as follows:
N
LV
DIR POS NAME

The first line defines the number of inhabitants (N<32000). Data set starting with value N=0 represents the end of the input file. The second line contains length of the world L(float) and velocity of inhabitants V(float). Both values are always positive. In next N lines the data about inhabitants are given in an order of increasing POS (positive direction):
DIR – initial direction (‘p’ or ‘P’ for positive and ‘n’ or ‘N’ for negative)
POS – position in the time of creation (0<=POS<=L)
NAME – name of inhabitant (string up to 250 characters)
Input values within one line are separated with at least one space and there will be no empty lines in input. You may assume that input is always correct and that each data set has only one unique solution.

Output

The output consists of one line per each input data set. The first value should be the time when the last inhabitant will fall of the linear world counting from the moment of creation. Value should be printed truncated to two decimal places in a field 13 characters wide. The second value should be the name of the inhabitant. Values should be separated with single space character.

Sample Input

1
13.5 2
p 3.5 Smarty
4
10 1
p 1 Helga
n 3 Joanna
p 5 Venus
n 7 Clever
0

Sample Output
     5.00 Smarty
     9.00 Venus

分析:

1.这道题求花费最长时间不难,遍历一遍即可找到,难点在于找到最后一个掉下去人的姓名。
2.我们可以认为蚂蚁相遇后名字会互相交换,并且擦肩而过,假设行进时间最长的蚂蚁为A,我们只需要关注在A的行进方向上有多少个和A反向的,就能知道会有多少只蚂蚁和真正的A碰头,但其实真正和A碰头的并不是最初和A反向的那些,而是在A初始方向上最靠近A的那几只蚂蚁,至于最终真正的A会带着谁的名字,只需要求出A的初始方向上有多少个初始方向和A反向的蚂蚁就行了,假设有cnt只,那么真正的A最后会携带A的初始方向上从A开始往前数cnt个的那只蚂蚁的名字,画画图就明白了。
3.需要注意,起始ma要初始化为-1,因为可能存在0.0;
4.因为是直接截取的小数点后两位,不是四舍五入,就不能直接%.2f,类似这么求,可以*100后强制转换一下再/100;
5.输出用%lf和%f的问题(后面有详细介绍)。
6.有时候题意没有分析到位就容易忽略条件,像我这样的英语战五渣就忽略了两个条件1.居民位置以递增的序列给出;2.输出数字应在13个字符宽的字段中被截断到小数点后两位。
题不算难,但容易坑,就这样吧,还是平时的一些习惯没有好好养成,wa了一晚上。。。。

AC代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int n,a,b,loc;
double l,v,ma;
bool flag;
struct node{
    double x;
    char direction[5];
    char na[255];
}s[32010];
int main(){
    while(~scanf("%d",&n)&&n){
        ma=-1;//起始ma要初始化为-1,因为可能存在0.0;
        a=b=0;
        scanf("%lf%lf",&l,&v);
        flag=false;
        for(int i=0;i<n;i++){
            scanf("%s%lf%s",&s[i].direction,&s[i].x,s[i].na);
            if(s[i].direction[0]=='p'||s[i].direction[0]=='P'){
                if(ma<l-s[i].x){
                    ma=l-s[i].x;
                    loc=i;
                    flag=true;
                }
            }
            else {
                if(ma<s[i].x){
                    ma=s[i].x;
                    loc=i;
                    flag=false;
                }
            }
        }
        if(flag){
            for(int i=loc;i<n;i++){
                if(s[i].direction[0]=='n'||s[i].direction[0]=='N')
                    a++;
            }
            loc+=a;
        }
        else{
            for(int i=loc;i>=0;i--){
                if(s[i].direction[0]=='p'||s[i].direction[0]=='P')
                    b++;
            }
            loc-=b;
        }
        printf("%13.2f %s\n",(int)(ma*100/v)/100.0,s[loc].na);
    }
    return 0;
}
关于输出用%lf和%f的问题

问:有人告诉我不能在printf中使用%lf。为什么printf()用%f输出double型,而scanf却用%lf呢?
答:printf的%f说明符的确既可以输出float型又可以输出double型。根据“默认参数提升”规则(在printf这样的函数的可变参数列表中,不论作用域内有没有原型,都适用这一规则)float型会被提升为double型。因此printf()只会看到双精度数。(严格地讲,%lf在printf下是未定义的,但是很多系统可能会接受它。要确保可移植性,就要坚持使用%f。)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值