UVA 10881(经典模拟,trick点)

点击打开链接


Piotr's Ants

"One thing is for certain: there is no stopping them;
the ants will soon be here. And I, for one, welcome our
new insect overlords."

Kent Brockman

Piotr likes playing with ants. He hasn of them on a horizontalpoleL cm long. Each ant is facing either left or right and walksat a constant speed of 1 cm/s. When two ants bump into each other, theyboth turn around (instantaneously) and start walking in opposite directions.Piotr knows where each of the ants starts and which direction it is facingand wants to calculate where the ants will end upT seconds from now.

Input
The first line of input gives the number of cases, N. Ntest cases follow. Each one starts with a line containing 3 integers:L ,T andn (0 <= n <= 10000).The nextn lines give the locations of then ants (measuredin cm from the left end of the pole) and the direction they are facing(L or R).

Output
For each test case, output one line containing "Case #x:"followed byn lines describing the locations and directions of then ants in the same format and order as in the input. If two or moreants are at the same location, print "Turning" instead of "L" or "R" fortheir direction. If an ant falls off the polebefore T seconds,print "Fell off" for that ant. Print an empty line after each test case.


sample input

2
10 1 4
1 R
5 R
3 L
10 R
10 2 3
4 R
5 L
8 R

sample output

Case #1:
2 Turning
6 R
2 Turning
Fell off

Case #2:
3 L
6 R
10 R


思路 

       一开始拿到这题的想法就是模拟蚂蚁相遇和落杆的情况,但是蚂蚁的数量很多,相遇次数也很多,这样模拟可行度很低。
       实际上,当蚂蚁因相遇而调头时,物理意义上的位置情况和两个蚂蚁对穿而过是一样的。也就是说,只需独立计算出每只蚂蚁在T时刻的位置即可。 
       虽然说位置是不变的,但是蚂蚁的id是改变的(也很好想,本来是相遇后调头,现在是直接穿过,id需要互换)。如果在每次相遇时互换id,那又要考虑相遇的情况,问题又麻烦了。实际上,还有一点很重要:所有蚂蚁的相对顺序是保持不变的
       利用这一特性,只需要对于前后两个状态按照位置先后排序。利用前状态排序得到每一个id在排序后杆上的位置,用order数组记录。对于后状态,排序后,用order数组映射出不同id所在的位置,取出其信息判断输出即可。




代码示例

#include<bits/stdc++.h>
using namespace std;

const int maxn=10010;

struct ant{
	int num;
	int pos;
	int flag;
	bool operator < (const ant & a) const{
		return pos<a.pos;
	}
}before[maxn],after[maxn];

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

int order[maxn];

int main()
{	
	//freopen("read.txt","r",stdin);
	//freopen("write.txt","w",stdout);
	std::ios::sync_with_stdio(false); 
	int N,T;
	cin>>N;
	T=N;
	int l,t,n;
	while(N--)
	{
		cin>>l>>t>>n;
		for(int i=0;i<n;++i){
			int pos,flag;
			char c;
			cin>>pos>>c;
			flag=(c=='L'?-1:1);
			before[i]=(ant){i,pos,flag};
			after[i]=(ant){0,pos+flag*t,flag}; 
		}
		
		sort(before,before+n);
		for(int i=0;i<n;++i) 
			order[before[i].num]=i;//这一步很关键,因为num是唯一的,所以order数组是填满的 
			//其相当于一个映射 即给一个key表示num(输入序号),返回value其在轴上的位置(左数第几个) 
		
		sort(after,after+n);
		for(int i=0;i<n-1;++i)
			if(after[i].pos==after[i+1].pos) after[i].flag=after[i+1].flag=0;
		
		
		cout<<"Case #"<<T-N<<':'<<endl;
		for(int i=0;i<n;++i){
			int a=order[i];
			if(after[a].pos<0||after[a].pos>l) cout<<"Fell off"<<endl;
			else cout<<after[a].pos<<' '<<dirname[after[a].flag+1]<<endl;
		}
		cout<<endl;
	}
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值