题解——来自风平浪静的明天(BFS)

题解——single(二次扫描+数学)

暴力BFS真出奇迹了


题面

Description
冬眠了五年,光终于从梦中醒来。
千咲、要,大家都在。
隐约记得“昨天”的海船祭,爱花意外成为贡女,沉入海底。
海面冰封,却有丝丝暖流在冰面之下涌动。
此时,爱花沉睡在祭海女神的墓地。她的胞衣在一点点脱落,化作一簇簇暖流,夹杂着她的感情,向海面上涌去。
爱花,你在哪里?
五年之后,纺已经成为海洋学研究科的大学生。
在纺的帮助下,光得知了海面下海流的情况。
纺告诉光,暖流一旦产生,就会不断地向四周扩散,直到遇到海中的岩石。
红腹海牛,快告诉光,爱花在哪里。
纺帮你绘制了一张海流情况图,长度为N,宽度为M。

然后私有题面隐藏了

Input
海图

Output
海花的位置

in.1
5 5
YYYHB
YYHHH
YHHXB
BBHBB
BBBBB

out.1
2 3

数据范围与约定

对于30%的数据,n,m<=10
对于70%的数据,n,m<=100
对于100%的数据,n,m<=300

思路

主要思路

对H暴力BFS扫,数据水,只要最后同时扫完H,那么枚举的该点合法,否则不合法。

细节

实际复杂度远低于 N^4 大概只要 N^3 多一点

#include<bits/stdc++.h>
using namespace std; 
const int MAXN = 305 ;
char s[ MAXN ] ;
int to[ 4 ][ 2 ] = { { 0 , 1 } , { 0 , -1 } , { 1 , 0 } , { -1 , 0 } } ;
int N , M , a[ MAXN ][ MAXN ] , dfn[ MAXN ][ MAXN ] , vis[ MAXN ][ MAXN ] , tot = 0 ;
bool  used[ MAXN ][ MAXN ]  ;//used记录ans  
queue< pair< int , int > >q ;//广搜 
void  Init(){
    scanf("%d%d",&N,&M) ;
    for( int i = 1 ; i <= N ; ++i ){
        scanf("%s",s);
        for( int j = 1 ; j <= M ; ++j )
            if( s[ j-1 ] == 'H' )a[ i ][ j ] = 1 , tot++ ;//暖流 
            else if( s[ j-1 ] == 'B' )a[ i ][ j ] = 2 ;//海洋
            else if( s[ j-1 ] == 'Y' )a[ i ][ j ] = 3 ;//沙滩 
            else if( s[ j-1 ] == 'X' )a[ i ][ j ] = 4 ;//暗礁 
    }
}
void lis(){
    for( int i = 1 ; i <= N ; ++i )
        for( int j = 1 ; j <= M ; ++j )
            if( a[ i ][ j ] == 1 ){
                cout<<i<<" "<<j; return ;
            }
}
bool bfs( int xxx , int yyy ){
    while( !q.empty() )q.pop() ;
    q.push( make_pair( xxx , yyy ) ) ;
    memset( vis ,0 , sizeof(vis) ) ;
    vis[ xxx ][ yyy ] = 1 ;
    int num = 1 ;
    while( !q.empty() ){
        int x = q.front().first , y = q.front().second ; q.pop() ;
        if( vis[ x ][ y ] != dfn[ x ][ y ] )used[ x ][ y ] = false ;
        //cout<<x<<" "<<y<<endl ;
        for( int i = 0 ; i < 4 ; ++i ){
            int xx = x+to[ i ][ 0 ] , yy = y + to[ i ][ 1 ] ;
            if(xx<=M&&xx>0&&yy>0&&yy<=M&&a[xx][yy]!=3&&a[xx][yy]!=4&&vis[xx][yy]==0){
                if(a[xx][yy]==1)
                {
                    num++;
                    vis[xx][yy]=1;
                    q.push(make_pair(xx,yy));
                    if(num==tot) 
                        return 1;
                }
                else return 0;
            }
        }
    }
    return 0 ;
}
int main(){
    freopen("calm.in","r",stdin) ;
    freopen("calm.out","w",stdout) ;
    Init() ;
    if( tot == 0 ){cout<<"-1";return 0 ;}
    if( tot == 1 ){lis(); return 0 ;} 
    for( int i = 1 ; i <= N ; ++i )
        for( int j = 1 ; j <= M ; ++j )
            if( a[ i ][ j ] == 1 )
                if( bfs( i , j ) ){
                    cout<<i<<" "<<j;
                    return 0 ;
                }
    cout<<-1 ;
    return 0 ;
}

备注:标程有锅,各位注意

如有不足,请大佬指出

转载于:https://www.cnblogs.com/ssw02/p/11477930.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值