UVa-10881-蚂蚁

这题目需要思考一下,我们其实不必纠结于蚂蚁的掉头问题,因为我们直接可以把蚂蚁看做擦肩而过,而不必对它进行调头之类的修改操作。

因为即使把蚂蚁看做擦肩而过,它们每个蚂蚁每个时刻所处的位置其实和掉头的结果是一样的,你们可以想一下是不是。

虽然每只蚂蚁的真实位置改变了,但是它们的相对位置其实并没有改变,我们依旧看一下蚂蚁擦肩而过之后的序列,可以很明显地发现,这个序列它们之间的相对位置其实并没有发生什么变化,所以我们最重要的工作就是按输入顺序输出结果。

因为我们要按照蚂蚁的位置升序排序,排序之后蚂蚁的位置已经改变了。

此时我们开辟一个order数组,我们在读入的时候再给每只蚂蚁按照顺序赋予一个id值。

然后第一次排序之后,我们就按照排序后的蚂蚁序列的id,从1-n进行写入。这样的话我们来分析一下,这样写入,首先肯定不是一定先写1里面,再写2里面,然后到n这样子,它肯定是随机地写入,因为排序之后打乱了。

但是我们的i值是从1-n进行变化的,我们这个i值就是排序之后,每个id的位置,我们对id也按照1-n的顺序写入,也就是说我们是顺序按id值作为下标写入,虽然写入并不是在数组中连续的。

但是我们可以得到一个好处,就是我们读出的时候,按照1-n顺序读出,此时我们就可以直接找到对应的第一次排序后的位置。

因为我们已经相当于是把它按照顺序写入的,所以order的下表就变成了id值,我们不一定有序写入,但是我们写完之后,它一定是按照升序存的。

这点还是请读者自行手演,比较清晰。这样子的话,我们就可以通过id值找到对应的第一次排序的位置,也可以通过相对位置不变进行输出。

另外读入的时候,要在第一个格式控制符后面加上空格,来读入输入中第一个数字之后除空格的第一个非空字符。

以下代码:

#include <cstdio> 
#include <algorithm>
using namespace std;
const int maxn=10000+5;
int L,T,n;
int order[maxn];

struct Ant {
	int id;
	int p;
	int d;
	bool operator < (const Ant &a)const {
		return p<a.p;
	}	
}before[maxn],after[maxn];

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

int main()
{
	int N,cnt=1;
	scanf("%d",&N);
	while (N--) {
		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+d*T,d};
		}
		/*for (int i=0;i<n;i++) {
			printf("%d %d %d
",ant[i].p,ant[i].d,ant[i].id);
		}*/
		sort(before,before+n);
		for (int i=0;i<n;i++) {
			order[before[i].id]=i;
		}
		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;
			}
		}
		printf("Case #%d:
",cnt++);
		for (int i=0;i<n;i++) {
			int a=order[i];
			if (after[a].p<0||after[a].p>L)
				printf("Fell off
");
			else
				printf("%d %s
",after[a].p,dirName[after[a].d+1]);
		}
		printf("
");
	}
	return 0;
}
原文地址:https://www.cnblogs.com/xyqxyq/p/10211334.html