zoukankan      html  css  js  c++  java
  • 开学考试题1:来自风平浪静的明天(bfs)

    题目:

    (鉴于题意描述过于糊,将这道题变成了一道阅读理解题,下面自己描述一遍题意)

    求一个位置,从那个位置出发向上下左右同时流,遇到B可以流,其它不能流,流出给出数据的样子。

    例如一个不合法的位置是2,5  。因为从它出发要流过上下左右的点,而给出的图中它的上下都是B,则说明没有被流过。

     

    ans=2 3

    分析:

    暴力:枚举每一个点是否能作为起点,bfs检查(不能用dfs!!)

    非正解但可以过:像刚刚给出的2,5这种点,它旁边是B,则说明它一定是最后一个流过的点,反推与它相邻的点,是倒数第二流过的点,一直向回推,直到推到起点。

    这种过程明显可以用bfs实现,用一个队列去存储每一个点是第几个被递推到。

    问题是这样推可能会推到多个起点,就把这些点存下来,再去bfs检查。(相当于一个剪枝,剪掉了许多不可能成为起点的点)

    如何检查:

    如果一个点旁边又有H又有B则不合法。

    #include<bits/stdc++.h>
    using namespace std;
    #define N 305
    #define nn N*N
    int dx[5]={0,0,1,-1},dy[5]={1,-1,0,0},x[nn],y[nn],id[N][N],h[N][N];
    bool vis[N][N],fl=false;
    char s[N],a[N][N];
    bool bfs(int now)
    {
        queue<int> qu;
        memset(vis,false,sizeof(vis));
        qu.push(now);
        while(!qu.empty()){
            int u=qu.front(); qu.pop();
            bool fl1=false,fl2=false;
            for(int i=0;i<=3;++i){
                int xx=x[u]+dx[i],yy=y[u]+dy[i];
                if(vis[xx][yy]) continue;
                if(a[xx][yy]=='H'){
                    vis[xx][yy]=true; qu.push(id[xx][yy]); fl1=true;
                }
                if(a[xx][yy]=='B') fl2=true;
                if(fl1&&fl2) return false;
            }
        }
        return true;
    }
    queue<int> q;
    int main()
    {
        freopen("calm.in","r",stdin);
        freopen("calm.out","w",stdout);
        int n,m,num=0,maxn=0,ans=0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) id[i][j]=++num,x[num]=i,y[num]=j;
        for(int i=1;i<=n;++i){
            scanf("%s",s);
            for(int j=1;j<=m;j++){
                a[i][j]=s[j-1];
                if(s[j-1]=='B') q.push(id[i][j]);
            } 
        }
        while(!q.empty()){
            int now=q.front(); q.pop(); 
            for(int i=0;i<=3;++i){
                int xx=x[now]+dx[i],yy=y[now]+dy[i];
                if(a[xx][yy]=='H' && !vis[xx][yy]){
                    q.push(id[xx][yy]);
                    vis[xx][yy]=true;
                    h[xx][yy]=h[x[now]][y[now]]+1;
                    maxn=max(maxn,h[xx][yy]);
                } 
            }
        }
        for(int i=1;i<=n;i++)
         for(int j=1;j<=m;j++)
          if(h[i][j]==maxn) 
           q.push(id[i][j]);
        while(!q.empty()){
            int now=q.front(); q.pop();
            if(bfs(now)) { ans=now; break; }
        }
        if(ans) printf("%d %d
    ",x[ans],y[ans]);
        else printf("-1
    ");
        return 0;
    }
    /*
    5 5
    YYYHB
    YYHHH
    YHHXB
    BBHBB
    BBBBB
    
    10 10
      12345678910
    1 YYBBBBBBXX
    2 YYBBBBBBBB
    3 XXBBBBBHBB
    4 BXXBBBHHHB
    5 BBXBBHHHHH
    6 BBBXXHXHHH
    7 BBBXXHHHHH
    8 BBBBXXHHXH
    9 XBBBXXXHXX
    10XXBBBBHHXX
    h: 
    0000000000
    0000000000
    0000000100
    0000001210
    0000012321
    0000020432
    0000034543
    0000005404
    0000000300
    0000001200
    */
    View Code
  • 相关阅读:
    formValidator4.1.1问题汇总
    什么,又是字符串拼接,我有些不淡定了
    webform下的分页辅助类再总结
    winform下的一个分页控件总结
    总结SQL Server窗口函数的简单使用
    sql复制表定义及复制数据行
    动态SQL开发基础和经验再总结
    c#执行定时计算限制操作(计时器)
    ado.net关于操作数据库的连接字符串整理
    使用Visual Studio实现WinForm多语言版本实例
  • 原文地址:https://www.cnblogs.com/mowanying/p/11478285.html
Copyright © 2011-2022 走看看