zoukankan      html  css  js  c++  java
  • [LUOGU]1141 01迷宫

    题目描述
    
    有一个仅由数字01组成的n×n格迷宫。若你位于一格0上,那么你可以移动到相邻4格中的某一格1上,同样若你位于一格1上,那么你可以移动到相邻4格中的某一格0上。
    
    你的任务是:对于给定的迷宫,询问从某一格开始能移动到多少个格子(包含自身)。
    
    输入输出格式
    
    输入格式:
    输入的第1行为两个正整数nm。
    
    下面n行,每行n个字符,字符只可能是0或者1,字符之间没有空格。
    
    接下来m行,每行2个用空格分隔的正整数i,j,对应了迷宫中第i行第j列的一个格子,询问从这一格开始能移动到多少格。
    
    输出格式:
    输出包括m行,对于每个询问输出相应答案。
    
    输入输出样例
    
    输入样例#1: 复制
    2 2
    01
    10
    1 1
    2 2
    输出样例#1: 复制
    4
    4
    说明
    
    所有格子互相可达。
    
    对于20%的数据,n≤10;
    
    对于40%的数据,n≤50;
    
    对于50%的数据,m≤5;
    
    对于60%的数据,n≤100,m≤100;
    
    对于100%的数据,n≤1000,m≤100000。

    非常艰难..
    第一次代码 暴力 70分

    #include<iostream>
    #include<string>
    #include<cstring>
    #define MAXN 1005
    using namespace std;
    
    int n,m;
    int a[MAXN][MAXN];
    int b[MAXN][MAXN];
    bool vis[MAXN][MAXN];
    int c[MAXN][MAXN];
    int cnt;
    
    int dx[4]={0,1,0,-1};
    int dy[4]={-1,0,1,0};
    
    void dfs(int x,int y){
        if(vis[x][y]) return;
        if(x<1||x>n||y<1||y>n) return;
        vis[x][y]=1;
        b[x][y]=1;
        cnt++;
        for(int i=0;i<=3;i++){
            int nx=x+dx[i];
            int ny=y+dy[i];
            if(a[nx][ny]==a[x][y]) continue;
            dfs(nx,ny);
        }
    }
    
    int calc(){
        int s=0;
        int i,j;
        for(i=1;i<=n;i++){
            for(j=1;j<=n;j++){
                if(b[i][j]) s++;
            }
        }
        return s;
    }
    
    void make(int num){
            for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(b[i][j]) c[i][j]=num;
            }
        }
    }
    
    int main(){
        string s;
        cin>>n>>m;
        int i,j;
        for(i=1;i<=n;i++){
            cin>>s;
            for(j=0;j<n;j++){
                a[i][j+1]=s[j]-'0';
            }
        }
        int x,y;
        while(m--){
            cin>>x>>y;
            if(!vis[x][y]){
                dfs(x,y);
                cnt=calc();
                make(cnt);
                memset(b,0,sizeof(b));
            }
            cout<<c[x][y]<<endl;
        }
        return 0;
    
    }

    cin改成scanf,试图写过getchar,不成功 80

    #include<iostream>
    #include<string>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #define MAXN 1005
    using namespace std;
    
    int n,m;
    int a[MAXN][MAXN];
    int b[MAXN][MAXN];
    bool vis[MAXN][MAXN];
    int c[MAXN][MAXN];
    int cnt;
    
    int dx[4]={0,1,0,-1};
    int dy[4]={-1,0,1,0};
    
    void dfs(int x,int y){
        if(vis[x][y]) return;
        if(x<1||x>n||y<1||y>n) return;
        vis[x][y]=1;
        b[x][y]=1;
        cnt++;
        for(int i=0;i<=3;i++){
            int nx=x+dx[i];
            int ny=y+dy[i];
            if(a[nx][ny]==a[x][y]) continue;
            dfs(nx,ny);
        }
    }
    
    int calc(){
        int s=0;
    
        for(register int i=1;i<=n;i++){
            for(register int j=1;j<=n;j++){
                if(b[i][j]) s++;
            }
        }
        return s;
    }
    
    void make(int num){
        for(register int i=1;i<=n;i++){
            for(register int j=1;j<=n;j++){
                if(b[i][j]) c[i][j]=num;
            }
        }
    }
    
    int main(){
    
        char s[1005];
        scanf("%d%d",&n,&m);
        register int i,j;
        for(i=1;i<=n;i++){
            scanf("%s",s);
            for(j=0;j<n;j++){
                a[i][j+1]=s[j]-'0';
            }
        }
    //  for(int i=1;i<=n;i++){
    //      for(int j=1;j<=n;j++){
    //          a[i][j]=getchar()-'0';
    //          if(a[i][j]<0||a[i][j]>1) j--;
    //          
    //      }
    //  }
        int x,y;
        while(m--){
            cin>>x>>y;
            if(!vis[x][y]){
                dfs(x,y);
                cnt=calc();
                make(cnt);
                memset(b,0,sizeof(b));
            }
            printf("%d
    ",c[x][y]);
    
        }
        return 0;
    
    }

    拍脑子一想,cnt在dfs时候就能记录了,没必要再来个n^2的循环。

    #include<iostream>
    #include<string>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #define MAXN 1005
    using namespace std;
    
    int n,m;
    int a[MAXN][MAXN];
    int b[MAXN][MAXN];
    bool vis[MAXN][MAXN];
    int c[MAXN][MAXN];
    int cnt;
    
    int dx[4]={0,1,0,-1};
    int dy[4]={-1,0,1,0};
    
    void dfs(int x,int y){
        if(vis[x][y]) return;
        if(x<1||x>n||y<1||y>n) return;
    
        vis[x][y]=1;
        b[x][y]=1;
        cnt++;
        for(register int i=0;i<=3;i++){
            int nx=x+dx[i];
            int ny=y+dy[i];
            if(a[nx][ny]==a[x][y]) continue;
    
            dfs(nx,ny);
        }
    }
    
    int calc(){
        int s=0;
    
        for(register int i=1;i<=n;i++){
            for(register int j=1;j<=n;j++){
                if(b[i][j]) s++;
            }
        }
        return s;
    }
    
    inline void make(int num){
        for(register int i=1;i<=n;i++){
            for(register int j=1;j<=n;j++){
                if(b[i][j]) c[i][j]=num;
            }
        }
    }
    
    int main(){
    
        char s[1005];
        scanf("%d%d",&n,&m);
        register int i,j;
        for(i=1;i<=n;i++){
            scanf("%s",s);
            for(j=0;j<n;j++){
                a[i][j+1]=s[j]-'0';
            }
        }
    //  for(int i=1;i<=n;i++){
    //      for(int j=1;j<=n;j++){
    //          a[i][j]=getchar()-'0';
    //          if(a[i][j]<0||a[i][j]>1) j--;
    //          
    //      }
    //  }
        int x,y;
        while(m--){
            cin>>x>>y;
            if(!vis[x][y]||!c[x][y]){
                cnt=0;
                dfs(x,y);
            //  cnt=calc();
                make(cnt);
                memset(b,0,sizeof(b));
            }
            printf("%d
    ",c[x][y]);
    
        }
        return 0;
    
    }

    然后想到没必要真的把每个点的值存进二位数组,因为无法同时和dfs完成,必须两步,慢。

    但是可以存一个数字进去,在一次dfs中,这个数字代表的是一类点,再用ans数组建立数字和答案(cnt)的映射,但是ans开小了,又RE了一个点。。

    AC代码:

    #include<iostream>
    #include<string>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #define MAXN 1005
    using namespace std;
    
    int n,m;
    int a[MAXN][MAXN];
    int b[MAXN][MAXN];
    bool vis[MAXN][MAXN];
    int c[MAXN][MAXN];
    int cnt;
    
    int dx[4]={0,1,0,-1};
    int dy[4]={-1,0,1,0};
    int ans[100005];
    int p=1;
    
    void dfs(int x,int y){
        if(vis[x][y]) return;
        if(x<1||x>n||y<1||y>n) return;
    
        vis[x][y]=1;
        c[x][y]=p;
        cnt++;
        for(register int i=0;i<=3;i++){
            int nx=x+dx[i];
            int ny=y+dy[i];
            if(a[nx][ny]==a[x][y]) continue;
    
            dfs(nx,ny);
        }
    }
    
    
    
    int main(){
    
        char s[1005];
        scanf("%d%d",&n,&m);
        register int i,j;
        for(i=1;i<=n;i++){
            scanf("%s",s);
            for(j=0;j<n;j++){
                a[i][j+1]=s[j]-'0';
            }
        }
    
        int x,y;
        while(m--){
            cin>>x>>y;
            if(!vis[x][y]){
                cnt=0;
                dfs(x,y);
                ans[p]=cnt;
                p++;
            }
            printf("%d
    ",ans[c[x][y]]);
    
        }
        return 0;
    
    }

    本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/9247542.html

  • 相关阅读:
    【鬼脸原创】github搭建动态网站
    WebStorm配置(2016/11/18更新)
    前端学习入门
    css笔记
    c# 将文本中的数据快速导入到数据库(200万左右的数据量)
    3.数据库单多表查询
    2.数据库表的增删改
    1.数据库建表
    浏览器的兼容性测试
    python-路径处理path
  • 原文地址:https://www.cnblogs.com/ghostcai/p/9247542.html
Copyright © 2011-2022 走看看