一二三四五 上山打老虎

CCF-CSP-2013-12-5I’m stuck!

链接:http://118.190.20.162/view.page?gpid=T1

思路:要求计算能由S到达的点,但是不能到达T的点的数目。从S点开始dfs一下后标记,然后从T逆向遍历标记。或者从s点开始bfs遍历一遍后把访问的点加到队列中,然后计算队列中能到达T点的数目。

代码:

#include<bits/stdc++.h>

using namespace std;
int n,m;
char s[100][100];
int b1[100][100],b2[100][100];
int dx[]={-1,0,+1,0};
int dy[]={0,1,0,-1};
bool check(int x,int y,int k){//技巧:通过方位移动
    char c=s[x][y];
    if(c=='+'||c=='S'||c=='T')return true;
    if(c=='-'&&(k%2))return true;
    if(c=='|'&&(k%2)==0)return true;
    if(c=='.'&&k==2)return true;
    return false;
}
void dfs1(int x,int y){
    b1[x][y]=1;
    for(int i=0;i<4;i++){
        int a=x+dx[i];
        int b=y+dy[i];
        if(b1[a][b])continue ;
        if(a<1||a>n||b<1||b>m)continue ;
        if(s[a][b]=='#')continue ;
        if(check(x,y,i))dfs1(a,b);
    }
}
void dfs2(int x,int y){
    b2[x][y]=1;
    for(int i=0;i<4;i++){
        int a=x+dx[i];
        int b=y+dy[i];
        if(b2[a][b])continue;
        if(a<1||b<1||a>n||b>m)continue;
        if(s[a][b]=='#')continue;
        if(check(a,b,i^2))dfs2(a,b);//由于是逆序检查,所以是检查(a,b)能否到达(x,y)点
    }
}
int main (){
    cin>>n>>m;
    int x,y;
    for(int i=1;i<=n;i++){
        cin>>(s[i]+1);
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
        if(s[i][j]=='S')dfs1(i,j);
        else if(s[i][j]=='T'){
            x=i;
            y=j;
        }
    }

    if(!b1[x][y]){
        puts("I'm stuck!");
    }
    else {
        int ans=0;
        dfs2(x,y);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            if(b1[i][j]&&!b2[i][j])ans++;
        cout<<ans;
    }


    return 0;
}

posted @ 2021-04-06 16:47  黒川川  阅读(111)  评论(0)    收藏  举报