算法竞赛入门经典的一道题
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
题目大意:一根长度为L厘米的木棍上有n只蚂蚁,每只蚂蚁要么朝左爬要么朝右爬,速度为1厘米/秒。当两只蚂蚁相撞时,二者同时掉头(掉头时间忽略不计)。给出每只蚂蚁初始位置和朝向,计算T秒之后每只蚂蚁的位置。
分析:在远处观察蚂蚁运动,由于黑点太小,所以当蚂蚁碰撞掉头时,看上去和两个点“对穿而过”没有任何区别。换句话说,如果把蚂蚁看成没有区别的小点,那么只需独立计算出每只蚂蚁在T时刻的位置即可。比如,3只蚂蚁,蚂蚁1=(3,R),蚂蚁2=(3,L),蚂蚁3=(4,L),则两秒钟之后,3只蚂蚁分别为(5,R),(1,L)和(2,L)。
而且所有蚂蚁的相对顺序保持不变,因此把所有目标位置从小到大排序,则从左到右的每个位置对应于初始状态下从左到右的每只蚂蚁。由于原题中的蚂蚁不一定按照从左到右的顺序输入,还需要预处理计算出输入中的第i只蚂蚁的序号order[i]。
/*
* =====================================================================================
*
* Filename: piotr_ants.c
*
* Description: 蚂蚁问题
*
* Version: 1.0
* Created: 2014年04月30日 21时46分02秒
* Revision: none
* Compiler: gcc
* =====================================================================================
*/
#include<stdio.h>
#define MAX 1000
struct ant{
int id;
int pos;
int dir;
}A[MAX],B[MAX];
int cmp(const void *a,const void *b);
int order[MAX];
int main(){
char dirname[][10]={"L","Turning","R"};
int m,i;
scanf("%d",&m);
for(i=0;i<m;i++){
int L,T,n;
int j,tem;
scanf("%d%d%d",&L,&T,&n);
for(j=0;j<n;j++){
char t;
int p;
scanf("%d %c",&p,&t);
A[j].id=j;
A[j].pos=p;
A[j].dir=(t=='L'?-1:1);
B[j].id=0;
B[j].pos=p+T*(A[j].dir);
B[j].dir=A[j].dir;
}
qsort(A,j,sizeof(A[0]),cmp);
for(j=0;j<n;j++){
tem=A[j].id;
order[tem]=j;
}
qsort(B,j,sizeof(A[0]),cmp);
for(j=0;j<n-1;j++){
if(B[j].pos==B[j+1].pos) B[j].dir=B[j+1].dir=0;
}
for(j=0;j<n;j++){
int a=order[j];
if(B[a].pos<0||B[a].pos>L){
printf("Fell off\n");
}else{
tem=B[a].dir+1;
printf("%d %s\n",B[a].pos,dirname[tem]);
}
}
printf("\n");
}
return 0;
}
int cmp(const void *a,const void *b){
struct ant *v1=(struct ant *)a;
struct ant *v2=(struct ant *)b;
return (v1->pos-v2->pos);
}
看了很久终于弄明白了。主要思想是蚂蚁在相邻两个蚂蚁中间,所以蚂蚁前后都会被挡住,所以蚂蚁的顺序不会变,所以记录其顺序,就能进行处理。原题给的c++的写法。我重新写了一个c的版本,就决问题以后感觉好舒畅!