CF1970F2 Playing Quidditch (Medium) 题解

· · 题解

点这里前往游记。

本来觉得这种大模拟挺无聊的,但是昨晚补题的时候发现把赛时 F1 的 AC 代码改一改不仅过了 F2,还同时抢到了 F1 F2 最短解,于是决定写一下 F2 的题解供参考。

因为题目保证了所有操作合法,所以我们记录需要的信息即可,如下:

当游走球 Bludger 移动到某一个位置时,扫一遍 map,如果这个位置有球员就按顺序把这个位置上的全部球员淘汰(由于 map 自动对第一关键字排序所以扫到直接输出即可);当某个球员移动到某一个位置时,如果 Bludger 在上面那么就将他淘汰掉。

如果你 WA on Test 5 并且数组下标和我一样是从 0 开始的,那么注意,场上可能没有 Bludger,此时如果一个球员到了 (0,0) 的位置,判断该位置上有没有 Bludger 时,因为 map 没有存储 Bludger 的信息,所以查出来的值也是 (0,0),如果你直接判相等就寄了。

剩下细节参考代码注释。

放代码:

#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;
}