• 九度oj 题目1159:坠落的蚂蚁


    题目描述:

        一根长度为1米的木棒上有若干只蚂蚁在爬动。它们的速度为每秒一厘米或静止不动,方向只有两种,向左或者向右。如果两只蚂蚁碰头,则它们立即交换速度并继续爬动。三只蚂蚁碰头,则两边的蚂蚁交换速度,中间的蚂蚁仍然静止。如果它们爬到了木棒的边缘(0或100厘米处)则会从木棒上坠落下去。在某一时刻蚂蚁的位置各不相同且均在整数厘米处(即1,2,3,…99厘米),有且只有一只蚂蚁A速度为0,其他蚂蚁均在向左或向右爬动。给出该时刻木棒上的所有蚂蚁位置和初始速度,找出蚂蚁A从此时刻到坠落所需要的时间。

    输入:

        第一行包含一个整数表示蚂蚁的个数N(2<=N<=99),之后共有N行,每一行描述一只蚂蚁的初始状态。每个初始状态由两个整数组成,中间用空格隔开,第一个数字表示初始位置厘米数P(1<=P<=99),第二个数字表示初始方向,-1表示向左,1表示向右,0表示静止。

    输出:

        蚂蚁A从开始到坠落的时间。若不会坠落,输出“Cannot fall!”

    样例输入:
    4
    10 1
    90 0
    95 -1
    98 -1
    样例输出:
    98

    这道题真的是又绕又难。一开始读题不认真,就没有搞清楚A蚂蚁到底指什么,最后才发现是“有且只有一只蚂蚁A速度为0”,这A也太隐蔽了吧!
    之后研究题目的内容,题目似乎在讲述动量守恒定律。若B蚂蚁撞了A蚂蚁,那么A蚂蚁就会像B蚂蚁一样运行下去。
    那么我们来研究一下A蚂蚁掉落的条件,一定有一只B蚂蚁撞了A蚂蚁,如果A前进的路上还有一只C蚂蚁,那么A会返回来直到碰上B.然后A会停下来,B的速度传给了C,C的速度传给了B.C和B对A的作用相互抵消了。
    向下推之,若A两侧有相同数目相向运动的蚂蚁,则A就不会掉下。
    若A两侧相向运动蚂蚁数目不相同,那么多的那一侧(抵消掉相同的后)离A最近的蚂蚁M会把它的速度传递给A,然后A就会掉下。
    那么这个时间其实就是M运动至边界的时间。

    注意只有在A两侧相向运动的蚂蚁才是有效的蚂蚁,其余都要忽略,另外速度为0的蚂蚁只有一只。
    代码如下
     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <algorithm>
     4 #include <iostream>
     5 using namespace std;
     6 
     7 struct Ant
     8 {
     9     int pos;
    10     int dir;
    11 };
    12 Ant ant[101];
    13 int pos[101];
    14 
    15 int cmp(const void *a, const void *b) {
    16     Ant at = *(Ant *)a;
    17     Ant bt = *(Ant *)b;
    18     return at.pos - bt.pos;
    19 }
    20 
    21 int main(int argc, char const *argv[])
    22 {
    23     int n;
    24     freopen("input.txt","r",stdin);
    25     while(scanf("%d",&n) != EOF) {
    26         for(int i = 0; i < n; i++) {
    27             scanf("%d %d",&ant[i].pos, &ant[i].dir);    
    28         }
    29         qsort(ant, n, sizeof(Ant), cmp);
    30         int left = 0;
    31         int right = 0;
    32         int Apos;
    33         int state = 0;
    34         int j = 0;
    35         for(int i = 0; i < n; i++) {
    36             if(state == 0 && ant[i].dir == 1) {
    37                 pos[j++] = ant[i].pos;
    38                 left++;
    39             }
    40             else if(state == 0 && ant[i].dir == 0) {
    41                 state = 1;
    42                 Apos = j;
    43                 pos[j++] = ant[i].pos;
    44                 
    45             }
    46             else if(state == 1 && ant[i].dir == -1) {
    47                 pos[j++] = ant[i].pos;
    48                 right++;
    49             }
    50         }
    51         if(left == right) {
    52             puts("Cannot fall!");
    53             continue;
    54         }
    55         else if(left > right) {
    56             int tmp = left - right;
    57             int ans = 100 - pos[tmp-1];
    58             printf("%d
    ",ans);
    59         }
    60         else {
    61             int tmp = right - left;
    62             int ans = pos[Apos + left+1];
    63             printf("%d
    ",ans);
    64         }
    65     }
    66     return 0;
    67 }
  • 相关阅读:
    vue 使用 <iframe> 嵌入网页 地址实现动态配置
    vue 视频播放 vue-video-player
    vue 实现自定义序号, 并且翻页序号累加。
    关于 vue 使用 Handsontable 表格数据导出
    node.js Stream流的使用
    手把手教如何搭建node+egg项目 引入Sequelize
    实现 通过数据库里一个字段值相等 则把 他合为一条数据
    最近在项目中碰到把对象数组转为键值对,
    js 的数组怎么push一个对象. Js数组的操作push,pop,shift,unshift JavaScrip
    for循环
  • 原文地址:https://www.cnblogs.com/jasonJie/p/5751019.html
Copyright © 2020-2023  润新知