floodfill 种子填充法 poj 2227

floodfill算法 建立一个队列Q。初始时,Q仅包含最开始的那个“点”,对于每个出队的元素,把他周围需要扩散到的元素加到队列中。为了避免重复访问,需要记录每个元素是否已经访问过,即访问标志。他是一种很常用的预处理方法,当“连在一起很大一块东西可以一并处理”的时候,可以作一次floodfill,分离出一个个“连在一起”的块,然后再做处理。
对于本题,经验告诉我们,“一个桶最大的容量取决于它最短的那块板”。所以我们先对周围的一圈格子进行访问,并取其中最短具有最短长度的格子,将其加入队列中。然后进行floodfill,搜索到没有被访问过的并且高度更低的格子即将当前访问的格子与刚出队的元素的高度差加入到答案中,并将该格子加入到队列中。

floodfill
floodfill算法 建立一个队列Q。初始时,Q仅包含最开始的那个“点”,对于每个出队的元素,把他周围需要扩散到的元素加到队列中。为了避免重复访问,需要记录每个元素是否已经访问过,即访问标志。他是一种很常用的预处理方法,当“连在一起很大一块东西可以一并处理”的时候,可以作一次floodfill,分离出一个个“连在一起”的块,然后再做处理。
对于本题,经验告诉我们,“一个桶最大的容量取决于它最短的那块板”。所以我们先对周围的一圈格子进行访问,并取其中最短具有最短长度的格子,将其加入队列中。然后进行floodfill,搜索到没有被访问过的并且高度更低的格子即将当前访问的格子与刚出队的元素的高度差加入到答案中,并将该格子加入到队列中。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
#define ll long long
const int maxn  = 333;
int dir[4][2] = { {1,0},{0,1},{-1,0},{0,-1} };
struct Pan{
    int x,y;
    int h;
    friend bool operator < (Pan a, Pan b) {
        return a.h > b.h;
    }
}pan;
priority_queue <Pan> Q;
int n,m;
int G[maxn][maxn];
bool vis[maxn][maxn];
ll ans;
void init() {
    memset(vis,0,sizeof(vis));
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
            if(i == 0 || j == 0 || i == n-1 || j == m-1) {
                pan.x = i ;pan.y = j;
                pan.h = G[i][j];
                Q.push(pan);
                vis[i][j] = 1;
            }
}
void floodfill() {
    Pan u, v;
    while(!Q.empty()) {
        u =Q.top(); Q.pop();
        for(int i=0;i<4;i++) {
            int x = u.x +dir[i][0];
            int y = u.y +dir[i][1];
            if(x<0 || x>=n || y<0 || y>=m) continue;
            if(vis[x][y]) continue;
            vis[x][y] = 1;
            v.x = x; v.y = y;
            if(G[x][y] < u.h) {
                ans += u.h - G[x][y];
                G[x][y] = u.h;
                v.h = G[x][y];
            }
            else {
                v.h = G[x][y];
            }
            Q.push(v);
        }
    }
    printf("%lld\n",ans);
}
int main() {
    while(~scanf("%d%d",&m,&n)) {
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                scanf("%d",&G[i][j]);
        init();
        ans = 0;
        floodfill();
    }
    return 0;
}

转载于:https://www.cnblogs.com/lenohoo/archive/2012/06/27/2564588.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值