1 条题解
-
0Takagi-san (njnu19200437) LV 10 MOD @ 2021-07-22 17:50:11
40%就不说了,直接模拟。
80%的数据,\(n\)非常小,\(m\)很大,这意味着我们可以直接跳到下一次发生冲突的时间去,而不是一秒一秒地模拟机器人的行为。
\(O(n^2)\)可以判断最近一次的冲突发生时间,然后进行删除和记录。所以整个算法的复杂度是\(O(n^3)\)到这一步还是相对容易的。
注意判断两个机器人相撞时间的函数,分四类情况讨论。
int cal(robot &r1, robot &r2) { if((r2.loc - r1.loc)%2 == 1) return 99999999; if(r1.vel == 'R' && r2.vel == 'R') return (2 * m - r1.loc - r2.loc) / 2; if(r1.vel == 'L' && r2.vel == 'L') return (r1.loc + r2.loc) / 2; if(r1.vel == 'R' && r2.vel == 'L') return (r2.loc - r1.loc) / 2; if(r1.vel == 'L' && r2.vel == 'R') return (2 * m - (r2.loc - r1.loc)) / 2; }
其他的代码如下:
#include<bits/stdc++.h> using namespace std; //Header struct robot{ int loc; int index; char vel; }; int n,m; void solve() { cin>>n>>m; robot a[n]; for(robot &i: a) cin>> i.loc; for(robot &i: a) cin>> i.vel; int b[n]; for(int i = 0; i < n; i++) b[i] = -1, a[i].index = i; while(1) { int minv = 99999999, loc1 = 1, loc2 = 1; for(int i = 0; i < n; i++) { for(int j = i + 1; j < n; j++) { if(cal(a[i], a[j]) < minv) { minv = cal(a[i], a[j]); // 求最近的碰撞事件 loc1 = i; loc2 = j; } } } if(minv == 99999999) break; b[a[loc1].index] = b[a[loc2].index] = cal(a[loc1], a[loc2]); for(int i = loc1; i < n-1; i++) a[i] = a[i+1]; n--; for(int i = loc2-1; i < n-1; i++) a[i] = a[i+1]; n--; //数组的删除,既然两个机器人碰撞, 则删去它们。 } for(int i: b) cout<<i<<" "; } int main() { solve(); return 0; }
对于\(100\%\)的数据,只能考虑线性的做法。容易发现位于奇数的机器人和位于偶数的机器人永远不会相撞,我们分别考虑。
比如对于奇数,我们考虑模拟"栈"的操作,从左到右加入一个个机器人。那么,我们考虑"LL","LR","RL","RR"四种相撞:
一旦当前是"R"而即将读入"L","R"一定与"L"碰撞而不是其他机器人,所以立即计算它们的碰撞时间,然后弹出它们。
若当前是"L"而即将读入"L",与即将读入的"L"碰撞一定比之后的要好。所以"LL"也是立即匹配,并弹出。第一轮处理的时候,先不要考虑"RR"的匹配,因为若后面可能再出现"L","RL"是优先碰撞的。
操作过后,栈的最底部至多有一个"L",之后全部是"R"。这样的话,应当先让"RR"进行匹配,"LR"留到最后匹配。
Code:
#include<bits/stdc++.h> using namespace std; //Header struct robot{ int loc; int index; char vel; }; int n,m; int cal(robot &r1, robot &r2) { if((r2.loc - r1.loc)%2 == 1) return 99999999; if(r1.vel == 'R' && r2.vel == 'R') return (2 * m - r1.loc - r2.loc) / 2; if(r1.vel == 'L' && r2.vel == 'L') return (r1.loc + r2.loc) / 2; if(r1.vel == 'R' && r2.vel == 'L') return (r2.loc - r1.loc) / 2; if(r1.vel == 'L' && r2.vel == 'R') return (2 * m - (r2.loc - r1.loc)) / 2; } void solve() { cin>>n>>m; robot a[n]; for(robot &i: a) cin >> i.loc; for(robot &i: a) cin >> i.vel; int b[n]; for(int i = 0; i < n; i++) b[i] = -1, a[i].index = i; vector<robot> v[2];//分成奇偶 for(robot i: a) v[i.loc%2].push_back(i); //以上是准备工作 for(int i = 0; i <= 1; i++) { vector<robot> tmp; for(robot it: v[i]) { int siz = tmp.size(); if(siz == 0) { tmp.push_back(it); continue; } if(it.vel == 'L') // LL, RL { b[tmp[siz-1].index] = b[it.index] = cal(tmp[siz-1], it); tmp.pop_back(); } else tmp.push_back(it); } while(tmp.size()>1) { int siz = tmp.size(); if(tmp[siz-1].vel == 'R') //RR, LR { b[tmp[siz-1].index] = b[tmp[siz-2].index] = cal(tmp[siz-2], tmp[siz-1]); tmp.pop_back(); tmp.pop_back(); } } } for(int i: b) cout<<i<<" "; } int main() { solve(); return 0; }
- 1
信息
- ID
- 1287
- 难度
- 8
- 分类
- (无)
- 标签
- (无)
- 递交数
- 41
- 已通过
- 6
- 通过率
- 15%
- 被复制
- 4
- 上传者