近来感觉脑袋有点抽,做几道思维题活动活动…
【UVa10881】Piotr’s Ants
Tags:数学 思维
题目描述
给定一根长为 L c m L\ cm L cm 的木棍和 n n n 只蚂蚁在初始时刻距木棍左端点的距离以及初始朝向( L L L 表示向左, R R R 表示向右)
蚂蚁运动速度为 1 c m / s 1\ cm/s 1 cm/s,要输出 T T T 秒后各蚂蚁的情况(蚂蚁相碰的瞬间速度反向)
输入
T T T 组。第一行输入组数 T T T。
对于每组数据,包含若干行,第一行三个整数 L , T , n L,T,n L,T,n,分别代表木棍长度、持续时间和蚂蚁数目。
接下来 n n n 行,每行一个整数和一个字符(字符仅限 ′ L ′ 'L' ′L′、 ′ R ′ 'R' ′R′),表示该蚂蚁距木棍左端的位置和朝向
范围: 0 ≤ n ≤ 10000 0 \le n \le 10000 0≤n≤10000。(没给 L L L 和 T T T 的范围)
输出
对于每组输入,首先输出一行 C a s e # n Case\# n Case#n( n n n 是数据组号,从 1 1 1开始)
然后输出每只蚂蚁的状态(要求安照输入次序
输出,而不是按照最终位置输出)
每只蚂蚁的状态输出一行:
- 如果该蚂蚁脱离了木棍(超出左端或右端),输出 F e l l o f f Fell\ off Fell off
- 否则,先输出蚂蚁距左端的位置,再输出其朝向情况(朝左是 L L L,朝右是 R R R,正在发生碰撞是 T u r n i n g Turning Turning)
输入样例
2
10 1 4
1 R
5 R
3 L
10 R
10 2 3
4 R
5 L
8 R
输出样例
Case #1:
2 Turning
6 R
2 Turning
Fell off
Case #2:
3 L
6 R
10 R
分析
e
m
m
m
.
.
emmm..
emmm.. 居然没有给
T
T
T 和
L
L
L 的范围啊!所以这道题 直接暴力模拟即可 需要开动一下小脑筋。
在脑子里稍微想象一下这个场景。其实蚂蚁相碰时瞬间速度反向是一个很特殊的条件。就好像蚂蚁直接互相 “穿过” 了一样。但是又不完全是这样,因为题目要求输出时按照输入次序
输出,所以蚂蚁们不是等价的,程序代码需要认得
,或者说记住
每只蚂蚁。
值得注意的是,蚂蚁们不管怎么相碰,他们的相对位置是不变的(任选一只蚂蚁,任意时刻后,其永远在其右的蚂蚁们的左侧,永远在其左的蚂蚁们的右侧),所以依靠这个就能在
T
T
T 秒后根据相对位置顺序辨别
每只蚂蚁的身份,从而给出正确的输出。
这样代码里面的各种来回映射一定不要弄混淆了。注意写代码的时候要好好取变量名!
时间复杂度:
排序 + 遍历, O ( n log n ) O(n\log n) O(nlogn) 的
AC代码
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define LL long long
#define sc(x) {register char _c=getchar(),_v=1;for(x=0;_c<48||_c>57;_c=getchar())if(_c==45)_v=-1;for(;_c>=48&&_c<=57;x=(x<<1)+(x<<3)+_c-48,_c=getchar());x*=_v;}
#define se(x) {register char _c=getchar(),_v=1;for(x=0;_c<48||_c>57;_c=getchar())if(_c==45)_v=-1;else if(_c==-1)return 0;for(;_c>=48&&_c<=57;x=(x<<1)+(x<<3)+_c-48,_c=getchar());x*=_v;}
#define PC putchar
template<typename T>void PRT(const T a){if(a<0){PC(45),PRT(-a);return;}if(a>=10)PRT(a/10);PC(a%10+48);}
template<typename T>void UPRT(const T a){if(a>=10)UPRT(a/10);PC(a%10+48);}
constexpr int MN(1e4 + 7);
enum State
{
L, R, M, O
};
struct Node
{
State sta;
int id;
int x;
inline bool operator <(const Node &o) const
{
return this->x < o.x;
}
} a[MN];
int id_to_rank[MN];
int main()
{
int T;
sc(T)
for (int cas=1; cas<=T; ++cas)
{
int len, t, n;
char dir;
sc(len)sc(t)sc(n)
for (int id=0; id<n; ++id)
{
sc(a[id].x)
scanf("%c", &dir);
a[id].sta = (dir == 'L' ? L : R);
a[id].id = id;
}
std::sort(a, a+n);
for (int i=0; i<n; ++i)
{
id_to_rank[a[i].id] = i;
if (a[i].sta == L)
{
a[i].x -= t;
if (a[i].x < 0)
a[i].sta = O;
}
else
{
a[i].x += t;
if (a[i].x > len)
a[i].sta = O;
}
}
std::sort(a, a+n);
for (int i=0; i<n; ++i)
{
if (i>0 && a[i-1].x==a[i].x || i<n && a[i+1].x==a[i].x)
a[i].sta = M;
}
printf("Case #%d:\n", cas);
for (int i=0; i<n; ++i)
{
const Node & now = a[id_to_rank[i]];
switch (now.sta)
{
case L:
PRT(now.x), PC(32), PC('L'), PC(10);
break;
case R:
PRT(now.x), PC(32), PC('R'), PC(10);
break;
case O:
puts("Fell off");
break;
case M:
PRT(now.x), PC(32), puts("Turning");
break;
}
}
PC(10);
}
return 0;
}