CF1970F2 Playing Quidditch (Medium) 题解
点这里前往游记。
本来觉得这种大模拟挺无聊的,但是昨晚补题的时候发现把赛时 F1 的 AC 代码改一改不仅过了 F2,还同时抢到了 F1 F2 最短解,于是决定写一下 F2 的题解供参考。
因为题目保证了所有操作合法,所以我们记录需要的信息即可,如下:
- 每个球员 / 球(在 F2 中包含鬼飞球 Quaffle 和游走球 Bludger)的位置,使用
std::map<std::string,std::pair<int,int> >存储; - 红方得分和蓝方得分,在进球时给对应的得分
+1 即可;
当游走球 Bludger 移动到某一个位置时,扫一遍 map,如果这个位置有球员就按顺序把这个位置上的全部球员淘汰(由于 map 自动对第一关键字排序所以扫到直接输出即可);当某个球员移动到某一个位置时,如果 Bludger 在上面那么就将他淘汰掉。
如果你 WA on Test 5 并且数组下标和我一样是从 map 没有存储 Bludger 的信息,所以查出来的值也是
剩下细节参考代码注释。
放代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int n,m,cr=0,cb=0; cin>>n>>m;
vector a(n,vector<string>(m));
for(auto &i:a)for(auto &j:i)cin>>j;
map<string,pair<int,int> > s; // map 用来记录位置
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
s[a[i][j]]=make_pair(i,j); // 记录初始位置
int q; cin>>q;
for(int i=0;i<q;i++){
string w; char op; cin>>w>>op;
auto &[x,y]=s[w];
switch(op){
case 'C':cin>>w; break;
// 这个操作在 F2 没啥意义,因为可以接的球只有一种
case 'U':x--; break; // 往上走
case 'D':x++; break; // 往下走
case 'L':y--; break; // 往左走
case 'R':y++; break; // 往右走
default:
if(a[x][y][1]=='G'){
if(a[x][y][0]=='R')cout<<i<<" BLUE GOAL\n",cb++;
else cout<<i<<" RED GOAL\n",cr++;
} // 扔球,统计得分
} // 按操作分类
if(w==".B"){
for(auto [p,l]:s)
if(p[0]!='.'&&l==s[w]) // 特判 .Q 的情况
cout<<i<<' '<<p<<" ELIMINATED\n";
} // 游走球到了某个位置,淘汰该位置上所有球员
else if(w!=".Q"){
if(s.find(".B")!=s.end()&&s[".B"]==s[w])
cout<<i<<' '<<w<<" ELIMINATED\n";
} // 球员到了某个位置,判断有没有鬼飞球
// 如果有再判断一下位置对不对
}
cout<<"FINAL SCORE: "<<cr<<' '<<cb<<endl;
return 0;
}