zoukankan      html  css  js  c++  java
  • 洛谷P1141 01迷宫

    非常难受了可以说..一道普及/提高-的水题
    我居然改了3天 提交了20次!!
    我太弱了!!


    正文开始:


    题目描述:

    有一个仅由数字 0 与 1 组成的 n×n 格迷宫。若你位于一格0上,那么你可以移动到相邻 4 格中的某一格 1 上,同样若你位于一格1上,那么你可以移动到相邻 4 格中的某一格 0 上。

    你的任务是:对于给定的迷宫,询问从某一格开始能移动到多少个格子(包含自身)。

    输入输出格式


    输入格式:

    第 1 行为两个正整数 n,m 。

    下面 n 行,每行 n 个字符,字符只可能是 0 或者 1 ,字符之间没有空格。

    接下来 m 行,每行 2 个用空格分隔的正整数 i,j ,对应了迷宫中第 i 行第 j 列的一个格子,询问从这一格开始能移动到多少格。


    输出格式:

    m 行,对于每个询问输出相应答案。

    分析题目:
    这道题一眼就能看出来是个搜索题(DP?不存在的)。那么一个显然的做法就是:把图存起来,对于每一个询问都进行一次dfs。显然这TLE了。(70分做法)

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<map>
    #include<set>
    #include<queue>
    #define INF 0x3f3f3f3f
    #define inf 0x3f
    #define ll long long
    using namespace std;
    queue<int> q;
    int n,m,x,a[1001][1001],y,dx[]={-1,1,0,0},dy[]={0,0,-1,1},sum,vis[1001][1001],ans[1001]; 
    char c;
    int dfs(int x,int y){
        vis[x][y]=1;
        for(int i=0;i<4;i++){
            int xx=x+dx[i];
            int yy=y+dy[i];
            if(a[x][y]==1){
                if(xx>0&&yy>0&&xx<=n&&yy<=n&&a[xx][yy]==0&&vis[xx][yy]==0) {
                    sum++;
                    dfs(xx,yy);
                }
            }
            if(a[x][y]==0){
                if(xx>0&&yy>0&&xx<=n&&yy<=n&&a[xx][yy]==1&&vis[xx][yy]==0) {
                    sum++;
                    dfs(xx,yy);
                }
            }
        }
        return sum;
    }
    int main(){ 
        sum=1;
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                vis[i][j]=0;
                cin>>c;
                if(c=='0') a[i][j]=0;
                if(c=='1') a[i][j]=1;
            }
        }
        for(int i=1;i<=m;i++){
            cin>>x>>y;
            ans[i]=dfs(x,y);
            sum=1;
            for(int j=1;j<=n;j++){
                for(int k=1;k<=n;k++){
                    vis[j][k]=0;
                }
            }
        }
        for(int i=1;i<=m;i++){
            cout<<ans[i]<<endl;
        }
        return 0;
    }

    那么如何做到AC呢?
    首先分析题目:

    若你位于一格0上,那么你可以移动到相邻 4 格中的某一格 1 上,同样若你位于一格1上,那么你可以移动到相邻 4 格中的某一格 0 上。

    那么我们可以做一个设想:对于每一个点,从这个点出发能到达的所有的点是一个值sum,那么从他能到达的任意一点出发,也能有一个值sum,并且这两个值相等。
    但是!如果从这个点A出发到达不了的点B,那么这个点B的答案和A不同。
    我们可以把他理解成一个连通块。
    巨坑:数组要开1e6,不然坐等WA或者RE吧qwq.

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<map>
    #include<set>
    #include<queue>
    #define INF 0x3f3f3f3f
    #define inf 0x3f
    #define ll long long
    using namespace std;
    queue<int> q;
    int n,m,x,a[1001][1001],y,dx[]={-1,1,0,0},dy[]={0,0,-1,1},sum,vis[1001][1001],ans[1000001],num[1000001];
    int k;
    char c;
    void dfs(int x,int y,int k){
        vis[x][y]=k;
        for(int i=0;i<4;i++){
            int xx=x+dx[i];
            int yy=y+dy[i];
            if(a[x][y]==1){
                if(xx>0&&yy>0&&xx<=n&&yy<=n&&a[xx][yy]==0&&vis[xx][yy]==0) {
                    sum++;
                    dfs(xx,yy,k);
                }
            }
            if(a[x][y]==0){
                if(xx>0&&yy>0&&xx<=n&&yy<=n&&a[xx][yy]==1&&vis[xx][yy]==0) {
                    sum++;
                    dfs(xx,yy,k);
                }
            }
        }
    }
    int main(){ 
        k=0;
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                vis[i][j]=0;
                cin>>c;
                if(c=='0') a[i][j]=0;
                if(c=='1') a[i][j]=1;
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(vis[i][j]==0){
                    k++;
                    sum=1;
                    dfs(i,j,k);
                    num[k]=sum;
                }
            }
        }
        for(int i=1;i<=m;i++){
            cin>>x>>y;
            int qwq=vis[x][y];
            ans[i]=num[qwq];
        }
        for(int i=1;i<=m;i++){
            cout<<ans[i]<<endl;
        }
        return 0;
    }
  • 相关阅读:
    单例模式
    分析GC日志
    JVM运行时参数
    JVM监控及诊断工具-GUI篇
    JVM监控及诊断工具-命令行篇
    性能监控与调优(概述篇)
    再谈类的加载器
    类的加载过程(类的生命周期)详解
    字节码指令集
    class文件结构
  • 原文地址:https://www.cnblogs.com/kenlig/p/9426878.html
Copyright © 2011-2022 走看看