洛谷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;
}

 

posted @ 2018-08-05 19:40  kenlig  阅读(383)  评论(1编辑  收藏  举报