NJUST 挺好的bfs题

water3

Time Limit: 1000ms

Memory Limit: 65536KB

Description

听说全球气候变暖,冰川融化,海水淹大地。着实好奇要融化多少冰川会淹没我的宿舍,哦不,淹没南京,反正NJUST应该总会是第一批被淹的。现将整个NJUST简化成一个N×M的棋盘。每个小格子代表一个区域,并且拥有一个值表示海拔。一个6×5的棋盘像下面这样:4 4 4 3 34 2 9 1 34 1 9 1 3 2 6 3 8 2 2 1 7 1 2 2 1 2 2 2大雨倾盆,水淹的到处都是。棋盘边缘不会有无限高的墙,而是什么都没有!也就是说,如果水没过了这个棋盘的四周边缘,水就会流出去。现在我们想知道这个棋盘最多能装多少水!每个地区每个单位海拔能装一单位的水。上图中,棋盘最后能装水的情况如下:4 4 4 3 34 4 9 3 34 4 9 3 3 2 6 6 8 2 2 1 7 2 2 2 1 2 2 2总计:13单位的水无论哪儿再多水,都会从边缘流走。

Input

多CASE,测试数据以EOF结尾,对于每个CASE:第一行两个整数N,M(1 <= N, M <= 300)。接下去N行,每行M个整数H(1 <= H <= 10^5)分别对应第i行j列的海拔。

Output

一个整数,表示最多能装多少水。

Sample Input

6 5
4 4 4 3 3
4 2 9 1 3
4 1 9 1 3 
2 6 3 8 2 
2 1 7 1 2 
2 1 2 2 2
5 4
5 8 7 7
5 2 1 5
7 1 7 1
8 9 6 9
9 8 9 9

Sample Output

13
12

网址https://icpc.njust.edu.cn/Contest/751/I/

题目大意:

问这个矩阵内部可以储存多少的水。


思路:

我们用vis表示已经访问过的点。然后将所有的点都bfs一遍,其中遍历的时候有一下条件

①不能超出矩阵的范围,那就continue

②如果搜索到了边缘,且边缘的值小于我们最初开始bfs的值,那就return

③因为搜索的时候会遇到在中心的一个坑,比如说测试数据中的第二组数据。其中的那个3的周围被4个比他大的值包围了,那么我们就要搜出周围比他大的最小值。

然后有了这些条件以后,我们每次修改高度的时候都把它修改成当前所要到的这个高度就可以了,这样就不需要多一个数组来考虑了。


#include
   
   
    
    
#include
    
    
     
     
#include
     
     
      
      
#include
      
      
       
       
#include
       
       
         #include 
        
          using namespace std; typedef pair 
         
           P; const int inf = 0x3f3f3f3f; const int maxn = 300 + 5; int n, m; int atlas[maxn][maxn]; bool vis[maxn][maxn]; long long res; int dx[] = {0, 0, -1, 1}; int dy[] = {1, -1, 0, 0}; void init(){ memset(atlas, 0, sizeof(atlas)); for (int i = 0; i < n; i++){ for (int j = 0; j < m; j++){ scanf("%d", &atlas[i][j]); } } res = 0; } //搜索周围比他大的就可以了 void bfs(int a, int b){ memset(vis, false, sizeof(vis)); vis[a][b] = true; queue 
          
         
       
      
      
     
     
    
    
   
   

que; vector > vec; long long tmp = 0; int high = atlas[a][b]; int mini = inf; vec.push_back(make_pair(a, b)); que.push(make_pair(a, b)); while (!que.empty()){ P p = que.front(); que.pop(); for (int i = 0; i < 4; i++){ int x = p.first + dx[i]; int y = p.second + dy[i]; if (x < 0 || x >= n || y < 0 || y >= m) continue; if (atlas[x][y] <= high && (x == 0 || x == n - 1 || y == 0 || y == m - 1)){ return ; } if (atlas[x][y] > high){ mini = min(mini, atlas[x][y]); continue; } if (vis[x][y] == true) continue; vis[x][y] = true; vec.push_back(make_pair(x, y)); que.push(make_pair(x, y)); } } if (mini == inf) return ; for (int i = 0; i < vec.size(); i++){ int x = vec[i].first; int y = vec[i].second; res += mini - atlas[x][y]; atlas[x][y] = mini; } } void solve(){ for (int i = 1; i < n - 1; i++){ for (int j = 1; j < m - 1; j++){ bfs(i, j); } } /*printf("check\n"); for (int i = 0; i < n; i++){ for (int j = 0; j < m; j++){ printf("%d ", atlas[i][j]); } printf("\n"); }*/ cout << res << endl; } int main(){ while (scanf("%d%d", &n, &m) == 2){ init(); solve(); } return 0; }






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值