1.1.5 蚂蚁。一根长度为L厘米的木棍上有n只蚂蚁,每只蚂蚁要么朝左爬,要么朝右爬,速度为1厘米/秒。

蚂蚁

题目来源 :《算法竞赛入门经典——训练指南》/刘汝佳,陈锋编著

一根长度为L厘米的木棍上有n只蚂蚁,每只蚂蚁要么朝左爬,要么朝右爬,速度为1厘米/秒。当两只蚂蚁相撞时,二者同时掉头(掉头时间忽略不计)。给出每只蚂蚁的初始位置和朝向,计算T秒之后每只蚂蚁的位置。
【输入格式】
输入的第一行为数据组数。每组数据的第一行为3个正整数L,T,n(0≤n≤10000);以下n行每行描述一只蚂蚁的初始位置,其中,整数x为蚂蚁距离木棍左端的距离(单位:
厘米),字母表示初始朝向(L表示朝左,R表示朝右)。
【输出格式】
对于每组数据,输出n行,按输入顺序输出每只蚂蚁的位置和朝向(Turning表示正在碰撞)。在第T秒之前已经掉下木棍的蚂蚁(正好爬到木棍边缘的不算)输出Fell off。
【样例输入】
2
10 1 4
1 R
5 R
3 L
10 R
10 2 3
4 R
5 L
8 R

【样例输出】

Case #1:
2 Turning
6 R
2 Turning
Fell off
Case #2:
3 L
6 R
10 R

示例代码

//代码来源:《算法竞赛入门经典——训练指南》/刘汝佳,陈锋编著.

#include
#include
using namespace std;
const int maxn = 10000 + 5;

struct Ant{
	int id; //enter order
	int p; //position
	int d; //direct -1 left, 0 turning, 1 right 
	
	bool operator<(const Ant& a) const{
		return p < a.p;
	}
}before[maxn], after[maxn];

const char dirName[][10] = {"L", "Turning", "R"};

int order[maxn]; //输入的第i只蚂蚁, 是终态中左数第order[i]只蚂蚁

int main(){
	int K;
	scanf("%d", &K);
	for(int kase = 1; kase <= K; kase++){
		int L, T, n; //length time numberOfAnts 
		printf("Case #%d:\n", kase);
		scanf("%d%d%d", &L, &T, &n);
		for(int i = 0; i < n; i++){
			int p, d;
			char c;
			scanf("%d %c", &p, &c);
			d = (c == 'L' ? -1 : 1);
			before[i] = (Ant){i, p, d};
			after[i] = (Ant){0, p+T*d, d}; //id is unknown
		}

		//order list
		sort(before, before+n);
		for(int i = 0; i <= n - 1; i ++)
			order[before[i].id] = i;

		//final
		sort(after, after+n);
		for(int i = 0; i < n-1; i++)
			if(after[i].p == after[i+1].p)
		 		after[i].d = after[i + 1].d = 0;// Turning 

		//output
		for(int i = 0; i < n; i++){
			int a = order[i];
			if(after[a].p < 0 || after[a].p > L)
				printf("Fell off\n");
			else
				printf("%d %s\n", after[a].p, dirName[after[a].d + 1]);
		}
		printf("\n");
	}
	return 0;
}

总结

  1. 所有蚂蚁的相对位置保持不变, 在不掉下木板的情况下, 所有的蚂蚁都可以看成是"往复运动"
  2. 朝向某方向蚂蚁的个数不变, 也就是说, 原来有2只朝右2只朝左的蚂蚁, 碰撞过后还是有2只朝右2只朝左的蚂蚁
  3. 蚂蚁碰撞的时候可以看成"对穿而过", 我们可以由此找出每个蚂蚁最终的位置和朝向(而不用在意是哪一只蚂蚁)
  4. 我们的逻辑是"知道最后一定会有蚂蚁在这个位置, 再去找应该在这个位置的蚂蚁", 而不是"由蚂蚁计算它最后的位置"
  5. 找到了"应该在这个位置的蚂蚁"之后, 这个蚂蚁的方向也就确定了(方向在第3步得出)
  6. 另外, 我们可以根据输入顺序给蚂蚁加一个标签(id), 来在最后的结果中选择输出
  • 在结构体中重载了<以排序
  • dirName 与 蚂蚁的 d + 1 相对应 便于输出
  • 使用0/1/-1代表蚂蚁状态

你可能感兴趣的:(1.1.5 蚂蚁。一根长度为L厘米的木棍上有n只蚂蚁,每只蚂蚁要么朝左爬,要么朝右爬,速度为1厘米/秒。)