【ATcoder】【DFS | 哈希 +并查集 | BFS 】Alternating Path

题目链接:

题意:

这个题目的意思是:给定一个h*w的方格内,只有' . ' 和 ' # ' 两个符号,

请问有多少条路径是  ' . '   ------>  ' # '  ,其中路径中必须是 ' . ' 和 ’ # ‘ 相间。


小结:

这个题真的不会做,我当时就懵逼了,啥都不知道,然后看了网友的做法,发现原来就是找联通块,只要找到联通块就行了,这个答案就是:

ans=每个联通块内 ' . ' 的个数  × ’ # ‘ 的个数

题解:

这个题提供了三种做法,第一种是DFS,就是抄袭网友的做法,第二种和第三种是看胜营哥的博客得知的。

其实如果我知道答案是求一个联通块,其实就很简单了,我就是题做得太少了。

第一种方法:是用到了vector < pair <int,int> >。其中,用到更多的是for( auto )这个结构来简化代码量

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e2+10;
char a[N][N];
typedef pair<int,int> P;
vector<P> V[N][N];
int n,m;
int dir[4][2]={
        {-1,0},
    {0,-1},{0,1},
        {1,0}
};
bool check(int x,int y){
    return x>=1&&x<=n&&y>=1&&y<=m;
}
int cnt[2];
bool vis[N][N];
void dfs(int x,int y){
    vis[x][y]=true;
    if(a[x][y]=='#'){
        cnt[0]++;
    }else{
        cnt[1]++;
    }
    for(auto v: V[x][y] ){
        if(!vis[v.first][v.second]){
            dfs(v.first,v.second);
        }
    }
}
int main()
{
    int h,w;
    scanf("%d%d",&h,&w);
    n=h,m=w;
    for(int i=1;i<=h;i++){
        scanf("%s",a[i]+1);
    }

    for(int i=1;i<=h;i++){
        for(int j=1;j<=w;j++){
            for(int k=0;k<4;k++){
                int tx=i+dir[k][0];
                int ty=j+dir[k][1];
                if(check(tx,ty)&&a[i][j]!=a[tx][ty]){
                    V[i][j].push_back(make_pair(tx,ty));
                }
            }
        }
    }
    ll ans=0;
    for(int i=1;i<=h;i++){
        for(int j=1;j<=w;j++){
            memset(cnt,0,sizeof(cnt));
            if(!vis[i][j]){
                dfs(i,j);
                ans+=1LL*cnt[0]*cnt[1];
            }
        }
    }
    printf("%lld\n",ans);
    return 0;
}

第二种方法:哈希+联通块:(胜营大佬提供的)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e2+10;
char a[N][N];
ll h,w,vis[N*N],Cnt[N*N],Dot[N*N],pre[N*N];
int dir[4][2]={
       {-1,0},
    {0,-1},{0,1},
        {1,0}
};
int Hash(int x,int y){
    return (x-1)*w+y;
}
int Find(int x){
    return x==pre[x]?x:Find(pre[x]);
}
void Merge(int x,int y){
    int fx=Find(x);
    int fy=Find(y);
    if(fx!=fy){
        pre[fy]=fx;
        Cnt[fx]+=Cnt[fy];
        Dot[fx]+=Dot[fy];
    }
}
bool check(int x,int y){
    return (x<1||y<1||x>h||y>w)?false:true;
}
int main()
{

    scanf("%lld%lld",&h,&w);
    for(int i=1;i<=h*w+10;i++){
        pre[i]=i;
    }
    for(int i=1;i<=h;i++){
        scanf("%s",a[i]+1);
    }
    for(int i=1;i<=h;i++){
        for(int j=1;j<=w;j++){
            Cnt[Hash(i,j)]++;
            if(a[i][j]=='.'){
                Dot[Hash(i,j)]++;
            }
        }
    }
    for(int i=1;i<=h;i++){
        for(int j=1;j<=w;j++){
            for(int k=0;k<4;k++){
                int tx=i+dir[k][0];
                int ty=j+dir[k][1];
                if(check(tx,ty)&&a[i][j]!=a[tx][ty]){
                    int Fx=Hash(i,j);
                    int Fy=Hash(tx,ty);
                    Merge(Fx,Fy);
                }
            }
        }
    }
    ll ans=0;
    for(int i=1;i<=h;i++){
        for(int j=1;j<=w;j++){
            int t=Hash(i,j);
            int Father=Find(t);
            if(!vis[Father]){
                ans=ans+(Cnt[Father]-Dot[Father])*Dot[Father];
                vis[Father]=1;
            }
        }
    }
    printf("%lld\n",ans);
    return 0;
}

第三种方法:其实求的东西都一样,但是就是写法上有丝毫差别。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=4e2+15;
int h,w,vis[N][N];
char a[N][N];
bool check(int x,int y){
    return (x<1||y<1||x>h||y>w)?false:true;
}
int dir[4][2]={
       {-1,0},
    {0,-1},{0,1},
        {1,0}
};
int main()
{
    scanf("%d%d",&h,&w);
    for(int i=1;i<=h;i++){
        scanf("%s",a[i]+1);
    }
    ll ans=0;
    for(int i=1;i<=h;i++){
        for(int j=1;j<=w;j++){
            if(!vis[i][j]){
                queue < pair<int,int> > Q;
                Q.push(make_pair(i,j));
                ll Dot,Well;
                Dot=Well=0;
                while(!Q.empty()){
                    pair<int,int> cur=Q.front();
                    Q.pop();
                    int x=cur.first;
                    int y=cur.second;
                    if(vis[x][y]==1)
                        continue;
                    //printf("[ %d,%d ]\n",x,y);
                    vis[x][y]=1;
                    a[x][y]=='.'?Dot++:Well++;

                    for(int k=0;k<4;k++){
                        int tx=x+dir[k][0];
                        int ty=y+dir[k][1];
                        if(!vis[tx][ty]&&check(tx,ty)&&a[x][y]!=a[tx][ty]){
                             Q.push(make_pair(tx,ty));
                        }
                    }
                }
                ans+=Dot*Well;
                //printf("(%d,%d) = %lld %lld %lld\n",i,j,Dot,Well,Dot*Well);
            }
        }
    }
    printf("%lld\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Z_sea/article/details/86440856
今日推荐