CF590C Three States(搜索)

我们把每个种族看作一个集合

已知最后他们联通,那么这就意味着他们到达某一点联通的代价是最小的

因此我们枚举所有点,找到最小值。

事实上,最后答案的连通块上面的点都是最小的,他们没有区别

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> pll;
const int N=3e7+10;
const int mod=1e9+7;
char s[1010][1010];
int n,m;
int dis[1010][1010][4];
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};
void bfs(int x){
    queue<pll> q;
    int i,j;
    for(i=1;i<=n;i++){
        for(j=1;j<=m;j++){
            if(s[i][j]=='0'+x){
                q.push({i,j});
                dis[i][j][x]=0;
            }
        }
    }
    while(q.size()){
        auto t=q.front();
        q.pop();
        int i;
        for(i=0;i<4;i++){
            int a=t.first+dx[i];
            int b=t.second+dy[i];
            if(a>=1&&a<=n&&b>=1&&b<=m){
                if(s[a][b]=='#')
                    continue;
                int v=(s[a][b]=='.');
                if(dis[a][b][x]>dis[t.first][t.second][x]+v){
                    dis[a][b][x]=dis[t.first][t.second][x]+v;
                    q.push({a,b});
                }
            }
        }
    }
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n>>m;
    int i,j;
    memset(dis,0x3f,sizeof dis);
    for(i=1;i<=n;i++){
        for(j=1;j<=m;j++)
            cin>>s[i][j];
    }
    bfs(1);
    bfs(2);
    bfs(3);
    ll ans=1e18;
    for(i=1;i<=n;i++){
        for(j=1;j<=m;j++){
            if(s[i][j]=='#')
                continue;
            ll tmp=0;
            for(int k=1;k<=3;k++){
                tmp+=dis[i][j][k];
            }
            if(s[i][j]=='.')
                tmp-=2;
            ans=min(ans,tmp);
        }
    }
    if(ans>1e9){
        cout<<-1<<endl;
    }
    else
        cout<<ans<<endl;
    return 0;
}
View Code
没有人不辛苦,只有人不喊疼
原文地址:https://www.cnblogs.com/ctyakwf/p/14396648.html