算法竞赛入门经典-训练指南(10881-Piotr's Ants)
题目大意:
一根长度为L的木棍一堆蚂蚁爬,向左或向右,速度都为1,若两蚂蚁碰撞则同时转头(转身时间忽略不计),问T时间之后每只蚂蚁的位置;
输入:t,(t个样例),每个样例输入 L,T,n,接下来是n行每行两个数据,一个POS(位置),一个dir(方向);
输出:按输入顺序输出每只蚂蚁的最终位置,若处于碰撞状态则输出Turning,掉下去输出”Fell off“;
解题思路:
本题类似于《挑战程序设计》的一道水题(POJ -1852 Ants),思路题;不过本题输入并不一定是按照位置大小进行输入的,因此,需要一个order数组进行预处理,具体看代码及注释;
AC代码:
#include <iostream> #include <algorithm> #include <cmath> using namespace std; /**************************************************** 样例: 2 10 1 4 1 R 5 R 3 L 10 R ****************************************************/ const int maxn = 10000; struct ant { int id; //输入顺序; int pos; //实际位置; int dir; //朝向: }before[maxn],after[maxn]; bool cmp(ant a,ant b) //按照位置进行排序 { return a.pos<b.pos; } const char dire[][10]={"L","Turning","R"}; //数组保存输出结果 int order[maxn]; //order数组的作用是保存各蚂蚁终态的相对位置; int main() { int t1; cin>>t1; for (int kase=1;kase<=t1;kase++) { cout<<"Case #"<<kase<<":"<<endl; int l,t,n; cin>>l>>t>>n; for (int i=0;i<n;i++) { int x; char c; cin>>x>>c; int d=(c=='L'?-1:1); before[i]=ant{i,x,d}; after[i]=ant{0,x+d*t,d}; //朝向依旧是d,因为必有一只蚂蚁的朝向是原来的d,比如(1,R)->(3,R),只不过不知道是那只蚂蚁; } sort(before,before+n,cmp); for (int i=0;i<n;i++) { order[before[i].id]=i; //before[i].id 是原来数组的输入顺序,现在before按照位置进行排序,那么此时对应的就是当前位置蚂蚁的编号; //比如样例中排序后before[1]是位置3的蚂蚁,其顺序为3,那么就是order[3]=2; //那么样例中的order就是 1 3 2 4; //之后after数组的输出after[order[1]].pos就是5这个位置的末位置; } sort(after,after+n,cmp); for (int i=0;i<n-1;i++) { if (after[i].pos==after[i+1].pos) { after[i].dir=after[i+1].dir=0; } } 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<<" "<<dire[after[a].dir+1]<< endl; } } cout<<endl; } return 0; }