Uva 10881 - Piotr's Ants( 转换思维 )

题目链接:

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=20&page=show_problem&problem=1822


题目大意:

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


题目分析:如《信息竞赛入门经典》中所述,由于掉头用的时间可以忽略不计,所以可以直接看做两只蚂蚁对穿而过。于是可以很开心的直接把坐标按照方向进行加 / 减的处理。得到某只蚂蚁的最终坐标。

把棍子拉为无限长,然后通过模拟这个过程可以发现,蚂蚁的顺序是绝对的,最左边的蚂蚁绝不可能爬到其他蚂蚁的右边去。所以将最终坐标从小到大排序就能够得到这只蚂蚁最终的位置。当然,如果最终蚂蚁的位置坐标小于 0 或者大于 L 那么就直接判断为Fell off。

此外,从题目所给的数据可以看得出,蚂蚁并不是按照顺序输出的,因此用数组存下输入的顺序就OK了。

P.S : 注意每组数据之间有个空行。


代码:

#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;

struct Ant {
	int enter_order, position, state;
	Ant (int e, int p, int s) { enter_order = e; position = p; state = s; }
};

const int maxn = 10000 + 5;
int order[maxn]; // 输入的第i只蚂蚁是队列中左数第order[i]只
int l, t, n;
int cases;
const char state[][10] = {"L", "Turning", "R"};

bool comp (Ant a1, Ant a2)
{
	return a1.position < a2.position;
}

int main()
{
	int i, j;
	int position, direction;
	char d;
	scanf("%d", &cases);
	for (i = 0; i < cases; i++) {
		vector<Ant> ini_ant, fin_ant;
		scanf("%d %d %d", &l, &t, &n);

		for (j = 0; j < n; j++) {
			scanf("%d %c", &position, &d);
			direction = (d == 'L' ? -1 : 1);

			Ant a1(j, position, direction);
			int new_position = position + t * direction;
			Ant a2(0, new_position, direction);      
			ini_ant.push_back(a1);
			fin_ant.push_back(a2);
		}
		
		// 计算order数组
		sort(ini_ant.begin(), ini_ant.end(), comp);
		for (j = 0; j < n; j++)
			order[ini_ant[j].enter_order] = j;

		// 对最终状态按照位置进行排序
		sort(fin_ant.begin(), fin_ant.end(), comp);
		for (j = 0; j < n-1; j++)
			if (fin_ant[j].position == fin_ant[j+1].position)
				fin_ant[j].state = fin_ant[j+1].state = 0;
	
		// 输出每只蚂蚁的对应结果
		printf("Case #%d:\n", i + 1);
		for (j = 0; j < n; j++) {
			int p = order[j];
			if (fin_ant[p].position < 0 || fin_ant[p].position > l)
				printf("Fell off\n");
			else
				printf("%d %s\n", fin_ant[p].position, state[fin_ant[p].state + 1]);
		}
		printf("\n");
	}
	return 0;
}



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值