BNU 26579 Andrew the Ant 【蚂蚁】

链接:




Andrew the Ant

4000ms
65536KB
64-bit integer IO format:  %lld      Java class name:  Main
Font Size:   
Type: 
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •                    
  •  

    Andrew the Ant is fascinated by the behavior of his friends. Thousands of them are marching their paths on and on. They can build highly organized ant-hills. Sometimes, however, they act a little bit stupidly.

    Recently, Andrew watched his fellow ants marching on top of a long piece of wood. He noticed their behavioral pattern is very simple: Each ant walks slowly forward with a constant speed of 1 cm per second. Whenever it meets another ant, both of them only touch with their antennae and immediately turn around and walk the opposite direction. If an ant comes to the end of the wood, it falls down and does not affect other ants anymore.

     

    The picture above shows an example of moving ants in time 0 s. In one second, the ants E and A meet at position 2 and change their directions. The ant A then meets B in the next 1.5 seconds. At the same time (2.5 seconds after the start), the ants C and D will meet too. All four of them change their directions. In the next 0.5 second (time 3 s), the first ant (E) falls down off the left end, etc.

    Your task is to simulate the movement of ants. For simplicity, suppose that the ants have zero size (although the picture could suggest something else).

     

     

    Input

     

    The input consists of several scenarios. Each scenario starts with a line containing two integer numbers L and A, separated by a space. L is the length of the wood in cms (1 ≤ L ≤ 99 999), and A is the number of ants at the beginning of the simulation (1 ≤ A ≤ L + 1).

    Then there are A lines, each containing a positive integer Xi, one space, and an uppercase letter. The number (0 ≤ X≤ L) specifies the position of the i-th ant and the letter its initial direction: either “L” for left (towards zero) or “R” for right. No two ants will start at the same position.

    Output

     

    For each scenario, you should print a single line containing the text “The last ant will fall down in T seconds - started at P.”, where T is the exact time when the last ant (or two) reaches the end of the wood, and P is the position where that particular ant has originally started in time 0. If two last ants fall down at the same time, print “started at P and Q”, indicating both of their positions, P <Q.

    Sample Input

    90000 1
    0 R
    10 1
    0 L
    14 5
    3 L
    6 L
    13 L
    8 R
    1 R

    Sample Output

    The last ant will fall down in 90000 seconds - started at 0.
    The last ant will fall down in 0 seconds - started at 0.
    The last ant will fall down in 13 seconds - started at 6 and 8.

    Hint

     

    (The last sample input scenario corresponds to the picture.)

    Source




    参考资料:lrj 《算法竞赛入门经典——训练指南》


    P9-P11:例题 5 蚂蚁 【UVa 10881 Piotr's Ants】

    再次膜拜神书 Orz



    题意:


    一根长度为 L 厘米的木棍上有 n 只蚂蚁,每只蚂蚁要么朝左爬,要么朝右爬,速度为 1厘米/秒。
    当两只蚂蚁相撞时,二者同时掉头(掉头时间忽略不计)。
    给出每只蚂蚁的初始位置和朝向,计算最后掉下去的蚂蚁所用的时间和该蚂蚁的初始位置。

    如果最后一刻有两只蚂蚁掉下去,那么按照它们的初始位置从左到右输出。【没注意这一点WA。。。】

    注意:由蚂蚁相遇就马上掉头可以知道,最后一刻至少有一只蚂蚁掉下去,而最多只可能有两只蚂蚁【一头一尾】。

    输入:第一行 L,N 
                L 代表木棍长度 (1 ≤ L ≤ 99 999)
                N 代表蚂蚁个数 (1 ≤ N ≤ L + 1).

    与 Uva 10881 的比较
    Uva 中是给出每只蚂蚁的初始位置和朝向, 计算 T 秒之后每只蚂蚁的位置。

    思路:

    其实是看的书上的关于 Uva 10081 的,自己就算能想到,也弄不了这么细致的。

    如果不区分蚂蚁的编号,那么蚂蚁相遇后的 “掉头” 不就可以看成是“对穿而过”

    比如,有 3 只蚂蚁,蚂蚁 1 = (1,R),  蚂蚁 2 = (3, L),  蚂蚁 3 = (4, L)
    则 2 s 后,3 只蚂蚁的状态分别为 (3, R), (1, L) 和 (2, L)。
    注意:这里只是确定了各个蚂蚁的位置,但是却忽略了,目标状态中的蚂蚁和初始状态中的蚂蚁的对应情况,也就是说弄混了“谁是谁”。

    但是注意到:相撞就掉头,所以蚂蚁的相对顺序是保持不变的。

    所以,只要把目标状态中的蚂蚁位置从小到大排序,则从左到右的每个位置对应于初始状态下从左到右的每只蚂蚁。
    注意:原题中蚂蚁不一定按照从左到右的顺序输入
                所以还需要预处理计算输入中的第 i 只蚂蚁的序号 order[i].


    与 Uva 10881 的比较和转换

    如果是 Uva 根据给你的时间 T 判断,T 时各个蚂蚁的状态。
    注意到:本题是算最后落下的蚂蚁的信息。
                   那么我们根据每个蚂蚁的初始位置,很容易计算出最后一只蚂蚁的落地时间 T 稍微改下 Uva 的代码即可。


    注意

    由题目样例知道:初始在边缘的而且往木棍外面走的蚂蚁最终下落时间记为 0

                                所以计算的时间 T 就按照最后一只到了边缘的蚂蚁用的时间 T 计算, 而不是 T-1。


    code:

    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    
    const int maxn =  99999+10;
    
    struct Ant{
    	int id; //输入顺序 
    	int p; //位置 
    	int d; //朝向。-1:左; 0:转身中;1:右 
    	bool operator < (const Ant& a) const { //按照 p 从左到右排序 
    		return p < a.p;
    	}
    }before[maxn], after[maxn]; //初始状态和最终状态 
    
    int order[maxn]; //输入的第 i 只蚂蚁是最终状态中的左数第 order[i] 只蚂蚁 
    
    struct Node{ //记录初始输入状态 
    	int p;
    	int d;
    }node[maxn];
    
    int id[2];//记录最后下落的蚂蚁的编号 
    
    int main()
    {
    	int L,n; //木棍长度和蚂蚁个数 
    	while(scanf("%d%d", &L,&n) != EOF)
    	{
    		int T = 0;
    		
    		for(int i = 0; i < n; i++)
    		{
    			int p, d;
    			char c;
    			scanf("%d %c", &p, &c);//输入因为第二个是字符注意添加空格
    			d = (c == 'L' ? -1 : 1);
    			
    			int t;
    			if(d == -1) t = p;
    			if(d == 1) t = L-p;
    			
    			T = max(T, t); //最后一只蚂蚁下落时间【正好到边缘】 
    			
    			node[i] = (Node) {p, d};
    		}
    		
    		for(int i = 0; i < n; i ++)
    		{
    			int p = node[i].p;
    			int d = node[i].d;
    			
    			before[i] = (Ant) {i, p, d}; //初始状态 
    			after[i] = (Ant){0, p+T*d, d}; //最终状态, id 未知, 可以忽略 d 
    		}
    		
    		//计算 order 数组 
    		sort(before, before+n); //按照蚂蚁的初始位置排序, 并未改变其 id 
    		for(int i = 0; i < n; i++)
    			order[before[i].id] = i; //输入的第 i 只蚂蚁是最终状态中的左数第 order[i] 只蚂蚁 
    		
    		//计算最终状态:按照蚂蚁位置从左到右排序	
    		sort(after, after+n);
    		
    		int index = 0; //记录最后一刻下落的蚂蚁个数 
    		for(int i = 0; i < n; i++)
    		{
    			int a = order[i];
    			if(after[a].p == 0 || after[a].p == L) id[index++] = i; //正好到边缘 
    		}
    		if(index == 1) //如果只有一只蚂蚁 
    		{
    			int p1 = node[id[0]].p;
    			printf("The last ant will fall down in %d seconds - started at %d.\n", T, p1);
    		}
    		
    		else if(index == 2) //如果有两只蚂蚁,按照初始位置从左到右输出 
    		{
    			int p1 = min(node[id[0]].p, node[id[1]].p);
    			int p2 = max(node[id[0]].p, node[id[1]].p);
    			printf("The last ant will fall down in %d seconds - started at %d and %d.\n", T, p1, p2);
    		}
    	}
    	return 0;
    }



    总结:


      第三场组队赛了,还是太过于浮躁,第一个 AC 的题是一道简单的 DP 一年前就做过的,很快的明确了思路,开始敲,这时Orc 在看蚂蚁的这一题。结果没有敲完就把编译器给弄坏了,然后把代码交个 Orc 各种改,我就各种安装编译器,最终 cb 还是弄坏了,只好装上很久以前用的 cfree 各种不习惯,还好这个时候 Orc 已经把 DP 改出来了,由于 int64 和 long long 问题 WA 了一次,马上AC了。已经过了一个小时了。排第6。。。各种悲催!

       然后 Orc 对我说 D 题是计算几何很多人过了,我马上去看 D 他继续看蚂蚁的这题。我看了下发现 D 不是计算几何而是简单的 BFS 才一百个点,但是没有看清楚题目中的英文,暂时猜测了下方向和骑士周游世界是一样的,然后我开始以这个思路敲,同时让Orc 也看看这题,方向是不是和我猜测的一样。然后很快就过了样例!问了下 Orc 决定交。惨淡的 TLE 。。。这可是 100 个点的 BFS 啊。。。。。。。然后让Orc检查,然后我发现是初始标记起点入队写错了,改了还是 TLE (此时贡献了两次TLE了)然后就是各种检查,各种数据测试,都没问题,最终快到 2 点的时候 Orc 发现我在输入的时候掉了 != EOF敲打 检查了那么久都没有发现问题啊!!!

       看了下排行榜这时两题第三吧,要是不白交两次 TLE 就应该是第二了。然后最后一题分巧克力的看有人过了,Orc猜测应该比较简单,但是我实在是看不懂题目就没有管了,然后看了下 F 有人过了,看了输入和输出发现和斐波拉契生兔子的有点像,再仔细看了下题目背景,发现是一水题,很快 AC 了,这时 2:49 了。3题排第三吧,学妹那支队伍这几次都表现的比较好,一直在我们前面,不是第一就是第二。然后又回来看最后一题,最终是 Orc 看懂了题目,然后我各种 YY 还是没有枚举分析完,比赛完了,Orc看了下题解说是斐波拉契。。。然后我看了下 B 的字符串 WA 的人很多,自己也没法下手,然后又去看了下 A 就是这道蚂蚁的题目,也发现了转换问题。。。正式开始写的时候只有半个小时了,很快写完了,但是计算时间的时候我是输入完了之后在计算 T 的,然后写 d  的时候不是算的每一个蚂蚁的,写错了,算成了最后一只蚂蚁的,样例和自己的数据都无法查出错误。。。。然后就这样 WA 到了比赛完。最后一题很多人做我们又没有写出来,最终 3 题排第 5 弱爆了,被两只老队伍踩外加两支新队伍踩。。。

        难题做不出,简单题读题速度不够快,写简单题目的时候心态又不够平和,各种小错误,导致很久才能 AC 。

        lrbj 回家了,每次还好有 Orc 来改错,然后基本上都是他先 AC 题目,避免了暴 0 的情况,比的心里也有点底吧。比赛基本上都看不到计算几何的题目,等 lrbj 来了三人合作情况应该会好一点,至少罚时什么的不会这么多了吧。看英文题目的速度会快一点,然后基础题目 AC 的速度应该也会快点。现在才越来越体会到合作的重要性。不过我们两个虽然每次敲代码的时候只用了一台电脑,但是却用了两台电脑看题目,也是自己单独敲的,这种习惯很不好,正式比赛一台电脑肯定是不会适应的了。


    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值