题解:P7479 至曾是英雄的您

Solution P7479

Idea

作为学过围棋的 OIer,我的第一反应是找眼。众所周知在围棋中双眼就是活棋。然后如果只有一个眼就要判断,具体你们上网搜。但是你会发现这个题不一样。

因为:这个题中白棋可以连续走

所以我们不能找眼。众所周知白棋只要把黑棋的气全堵住就可以让黑棋死了。我们需要把黑棋的气找出来,我们记为蓝棋。

然后需要判断由蓝棋组成的四连通块是否合法。所谓合法,就是指这一块蓝棋有气。例如:(下列 @ 代表蓝棋)

***
*@*
***

是不合法的,

*****
*@@@*
*@.@*
*@@@*
*****

是合法的,因为 @ 连通块有气。

所以可以用 bfs 判断一块蓝棋连通块是否合法。

Code

下面代码中 + 代表蓝棋。

#include<bits/stdc++.h>
using namespace std;
const int N=2005;
char ch[N][N];
int n,m;
bool vis[N][N];
const int dx[5]={0,1,-1,0,0};
const int dy[5]={0,0,0,-1,1};
bool in(int x,int y){
    if(x<0||x>n||y<0||y>m)return false;
    return true;
}
bool dfs(int x,int y){
    vis[x][y]=1;
    bool f=0;
    for(int i=1;i<=4;i++){
        int nx=x+dx[i],ny=y+dy[i];
        if(ch[nx][ny]=='.')f=1;
        if(in(nx,ny)&&ch[nx][ny]=='+'&&!vis[nx][ny])f|=dfs(nx,ny);
    }
    return f;
}
void solve(){
    cin>>n>>m;
    for(int i=0;i<=n+1;i++){
        for(int j=0;j<=m+1;j++){
            ch[i][j]='}';
            vis[i][j]=0;
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>ch[i][j];
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(ch[i][j]!='*')continue;
            for(int k=1;k<=4;k++){
                int nx=i+dx[k],ny=j+dy[k];
                if(ch[nx][ny]=='.')ch[nx][ny]='+';
            }
        }
    }
    int cnt=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(cnt>=2){
                i=n+1;
                j=m+1;
                continue;
            }
            if(ch[i][j]=='+'){
                if(!vis[i][j]&&!dfs(i,j))cnt++;
            }
        }
    }
    if(cnt<2)cout<<"NO\n";
    else cout<<"YES\n";
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int T;
    cin>>T;
    while(T--)solve();
}
posted @ 2024-11-28 15:57  Weslie_qwq  阅读(10)  评论(0)    收藏  举报  来源