識海社群打卡-4

夏尾草發表於2024-11-13

今天打卡大模擬

Problem - 1365D - Codeforces

image-20241113234004941

大模擬確實噁心人,但作為最臭的屎平時還是得多吃點,大模擬的特點是思路不算很難但程式碼真的很長很長,一個不小心哪裡寫得有問題查錯就是半天,各種細節都要很注意,對於提升自己查錯能力和快速寫題能力還是很有幫助的,這種屎雖然噁心但是就是得多吃。

簡單說下題意,大概就是給定一個網格圖,網格圖有四種符號,#代表牆,B代表bad壞人,G代表good好人, "."代表空白,可以把一些空白變成牆,然後使所有好人能跑走,壞人留下,並且只有跑到[n,m]才算逃出生天。

思路很簡單,就是把所有壞人都關起來,好人不能和壞人相鄰,並且好人沒有被關起來的。

程式碼實現

#include <bits/stdc++.h>
using namespace std;
const char nl = '\n';
#define all(x) (x).begin(), (x).end()
typedef long long ll;
typedef long double ld;
typedef long long int lli;
const int MOD = 1'000'000'007;
constexpr int inf = 1e9;

constexpr int dx[] = {0, 0, -1, 1}, dy[] = {-1, 1, 0, 0};

void solve()
{
  int n, m;
  cin >> n >> m;
  vector<string> a(n);
  int res = 0;
  for (int i = 0; i < n; i++)
  {
    cin >> a[i];
    res += count(a[i].begin(), a[i].end(), 'G');
  }
  if (res == 0)
  {
    cout << "YES" << nl;
    return;
  }
  a[n - 1][m - 1] = 'G';
  for (int i = 0; i < n; i++)
  {
    for (int j = 0; j < m; j++)
    {
      if (a[i][j] == 'B')
      {
        for (int k = 0; k < 4; k++)
        {
          int x = j + dx[k], y = i + dy[k];
          if (x < m && x >= 0 && y >= 0 && y < n)
          {
            if (a[y][x] == 'G')
            {
               cout << "NO" << nl;
              return;
            }
            if (a[y][x] == '.')
            {
              a[y][x] = '#';
            }
          }
        }
      }
    }
  }

  vector<vector<bool>> vis(n, vector<bool>(m));
  queue<pair<int, int>> q;
  vis[n - 1][m - 1] = 1;
  q.emplace(n - 1, m - 1);
  while (!q.empty())
  {
    auto [i, j] = q.front();
    q.pop();
    for (int k = 0; k < 4; ++k)
    {
      int x = i + dx[k], y = j + dy[k];
      if (0 <= x && x < n && 0 <= y && y < m && a[x][y] != '#' && !vis[x][y])
      {
        
        vis[x][y] = true;
        q.emplace(x, y);
      }
    }
  }

  for(int i = 0;i < n;i++){
    for(int j = 0;j < m;j++){
      if(a[i][j] == 'G' && !vis[i][j]){
        cout << "NO" << nl;
        return;
      }
    }
  }
 
  cout << "YES" << nl;
}

int main()
{
  ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
  int t = 1;
  cin >> t;
  while (t--)
  {
    solve();
  }
  return 0;
}

程式碼的思路就是先查詢有沒有好人,如果沒有就直接把出口堵上就好了所以肯定是yes因為題目保證了出口是空白

其次是把最後的位置變為一個好人,因為當好人和壞人分別在出口的上方和左方時是不行的,直接把這種情況算到好人和壞人相鄰就行,然後查詢好人與壞人相鄰的情況,並且把所有壞人都關上。

最後是從出口開始查詢對於所有通出口的地方都標記為1,所有不通的地方都標為0,然後查詢好人被關的情況就行。