题目大意:一根长度为L的杆上有N只蚂蚁,每只蚂蚁要么往左爬,要么往右爬,速度为1.两只蚂蚁相撞,同时掉头。杆子最左端为0,问T间时各蚂蚁的位置和方向。
解题思路:两只蚂蚁相撞与穿过效果一样。因此我们直接计算蚂蚁相遇直接穿过的结果即可。但是我们需要记录每只蚂蚁的方向,其实我们按照穿过计算时,朝左的个数和朝右的个数以及顺序不会变,但是蚂蚁的位置变了,但是真正蚂蚁的相对位置没有变,即最左边的还在最左边,左边第二个还在左边第二个。因此我们只需给蚂蚁加一个编号,按照编号给蚂蚁在更新一下状态即可。比如:有一个蚂蚁在排第三,但是它朝左走了之后变成了第一个,那么原来第一个蚂蚁的状态就是现在这个蚂蚁的状态。我们只需将现在的顺序更新到之前的蚂蚁身上即可。
AC代码:
#include <iostream>
#include <cstdio>
#include <map>
#include <algorithm>
using namespace std;
struct Ants
{
int x;
int id;
int z;
bool operator< (Ants a)const
{
return this->x < a.x;
}
}A[10005];
map<int, int> mp;
int main()
{
int T;
cin >> T;
for(int Case = 1; Case <= T; Case++)
{
mp.clear();
int l, t, n;
scanf("%d%d%d", &l, &t, &n);
char s[10];
int x;
for(int i=0; i<n; i++)
{
scanf("%d%s", &x, s);
A[i].id = i;
if(s[0] == 'R') A[i].z = 1; //朝右走
else A[i].z = -1; //朝左走
A[i].x = x;
}
sort(A, A+n);//让蚂蚁从左到右站好
for(int i=0; i<n; i++)
{
mp[ A[i].id ] = i; //记录原来蚂蚁的顺序
A[i].x += A[i].z * t;//更新位置
}
sort(A, A+n);//更新顺序
printf("Case #%d:\n", Case);
for(int i=0; i<n; i++)
{
int cur = mp[i];
if(A[cur].x < 0 || A[cur].x > l) printf("Fell off\n"); //从杆子上掉下来了
else if(cur +1 < n && A[cur].x == A[cur+1].x) //判断是否右跟这个蚂蚁在同一个位置的
{
if(A[cur].z + A[cur+1].z == 0) printf("%d Turning\n", A[cur].x); //位置相同,方向相反,正在相撞
else if(A[cur].z == -1) printf("%d L\n", A[cur].x);
else printf("%d R\n", A[cur].x);
}
else if(cur -1 < n && A[cur].x == A[cur-1].x) //判断是否右跟这个蚂蚁在同一个位置的
{
if(A[cur].z + A[cur-1].z == 0) printf("%d Turning\n", A[cur].x); //正在相撞
else if(A[cur].z == -1) printf("%d L\n", A[cur].x);
else printf("%d R\n", A[cur].x);
}
else
{
if(A[cur].z == -1) printf("%d L\n", A[cur].x);
else printf("%d R\n", A[cur].x);
}
}
printf("\n");
}
return 0;
}
蓝书代码:
// UVa10881 Piotr's Ants
// Rujia Liu
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 10000 + 5;
struct Ant {
int id; // 输入顺序
int p; // 位置
int d; // 朝向。 -1: 左; 0:转身中; 1:右
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;
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是未知的
}
// 计算order数组
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;
// 输出结果
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;
}