今天打卡大模擬
Problem - 1365D - Codeforces
大模擬確實噁心人,但作為最臭的屎平時還是得多吃點,大模擬的特點是思路不算很難但程式碼真的很長很長,一個不小心哪裡寫得有問題查錯就是半天,各種細節都要很注意,對於提升自己查錯能力和快速寫題能力還是很有幫助的,這種屎雖然噁心但是就是得多吃。
簡單說下題意,大概就是給定一個網格圖,網格圖有四種符號,#代表牆,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,然後查詢好人被關的情況就行。