POJ 2227 The Wedding Juicer FloodFill算法

POJ 2227 The Wedding Juicer FloodFill算法

这题看了以后,想了一个很脑残的做法,也过了,不过用了1.2s,哈哈。
后来看了一个高中生大牛写的 Pascal 程序。
根据函数名字来看,它用的是 floodfill 算法,提交了发现居然才用了188ms。
现在高中生真太牛逼了!佩服!
同时,作为一个即将毕业的大学生,哥表示压力很大。。
以前没见过这个算法,看了一下,发现看不大懂,但是这样做确实很有道理!
在网上面搜了一下关于floodfill算法的资料,发现很杂,还是看不大懂。。

算法的思想就是:
每个点都有一个水位,水位最小值为这个点的高度。
首先把边缘一周的点加入堆,这些点的水位初始化为点的高度。
每次都取出最小水位的点,将点周围的四个点里面,从来没有被加入过堆的点加入堆中,如果有的点的高度比水位低,那么就更新答案。
删除最小水位的点,然后重复上一步。直到不存在没有被加入过堆中的点为止。

用 C 再写了一遍,小小改动,慢了 100ms。

#include  < stdio.h >

#define  SIZE 332

struct  heap_node  {
    
int x, y;
}
;

int  W, H;
int  map[SIZE][SIZE], fil[SIZE][SIZE];
struct  heap_node heap[SIZE  *  SIZE];
int  heap_size, left, ans;

inline 
int  cmp( struct  heap_node  * a,  struct  heap_node  * b)
{
    
return fil[a->y][a->x] - fil[b->y][b->x];
}


inline 
void  shift_down( int  idx)
{
    
struct heap_node val = heap[idx];
    
    
while (1{
        idx 
*= 2;
        
if (idx > heap_size)
            
break;
        
if (idx + 1 <= heap_size && cmp(&heap[idx + 1], &heap[idx]) < 0)
            idx
++;
        
if (cmp(&val, &heap[idx]) <= 0)
            
break;
        heap[idx 
/ 2= heap[idx];
    }

    heap[idx 
/ 2= val;
}


inline 
void  shift_up( int  idx)
{
    
struct heap_node val = heap[idx];
    
    
while (1{
        
if (idx / 2 <= 0)
            
break;
        
if (cmp(&heap[idx / 2], &val) <= 0)
            
break;
        heap[idx] 
= heap[idx / 2];
        idx 
/= 2;
    }

    heap[idx] 
= val;
}


inline 
void  insert( int  y,  int  x,  int  f  =   - 1 )
{
    
if (y < 0 || y >= H || x < 0 || x >= W || fil[y][x])
        
return ;
    
if (map[y][x] > f)
        f 
= map[y][x];
    
else
        ans 
+= f - map[y][x];
    fil[y][x] 
= f;
    heap_size
++;
    heap[heap_size].y 
= y;
    heap[heap_size].x 
= x;
    shift_up(heap_size);
    left
--;
}


inline 
void  extract()
{
    heap[
1= heap[heap_size--];
    shift_down(
1);
}


int  main()
{
    
int i, j;

    freopen(
"e:\\test\\in.txt""r", stdin);

    scanf(
"%d%d"&W, &H);
    
for (i = 0; i < H; i++)
        
for (j = 0; j < W; j++)
            scanf(
"%d"&map[i][j]);
    
    left 
= W * H;
    
for (i = 0; i < H; i++{
        insert(i, 
0);
        insert(i, W 
- 1);
    }

    
for (i = 1; i < W - 1; i++{
        insert(
0, i);
        insert(H 
- 1, i);
    }


    
while (left) {
        i 
= heap[1].y;
        j 
= heap[1].x;
        extract();
        insert(i 
- 1, j, fil[i][j]);
        insert(i 
+ 1, j, fil[i][j]);
        insert(i, j 
- 1, fil[i][j]);
        insert(i, j 
+ 1, fil[i][j]);
    }


    printf(
"%d\n", ans);

    
return 0;
}


Pascal:
Pascal:
{$m $100000} {由于我是做的DFS进行FLOODFILL,所以不免开了点栈深度}

Program Gp ;

const
    maxn 
=   300  ;
    dx : array[ 
0  ..  3  ] of  - 1  ..  1   =  (  0  ,  1  ,  0  ,  - 1  ) ;
    dy : array[ 
0  ..  3  ] of  - 1  ..  1   =  (  1  ,  0  ,  - 1  ,  0  ) ;
    zy 
=  trunc( 1e9 ) ;

type
    heaptype 
=
        record
            x , y , val : longint ;
        end ;

var
    map , f             : array[ 
0  .. maxn ,  0  .. maxn ] of longint ;
    use , u             : array[ 
0  .. maxn ,  0  .. maxn ] of boolean ;
    heap                : array[ 
0  .. maxn  *  maxn ] of heaptype ;
    n , m , ans , len   : longint ;
    cant                : boolean ;

procedure init ;
var
    i , j : longint ;
begin
    fillchar( f , 
sizeof ( f ) ,  0  ) ;
    readln( m , n ) ;
    
for  i : =   1  to n  do
        
for  j : =   1  to m  do
        begin
            read( map[ i , j ] ) ; f[ i , j ] :
=  zy ;
        end ;
end ;

procedure ins( x , y , val : longint ) ;
var
    t       : heaptype ;
    i       : longint ;
begin
    t.x :
=  x ; t.y : =  y ; t.val : =  val ;
    inc( len ) ; i :
=  len ;
    
while  ( i  <>   1  ) and ( heap[ i div  2  ] . val  >  val )  do
    begin
        heap[ i ] :
=  heap[ i div  2  ] ;
        i :
=  i div  2  ;
    end ;
    heap[ i ] :
=  t ;
end ;

procedure sort( ii : longint ) ;
var
    j      : longint ;
    num    : heaptype ;
begin
    num :
=  heap[ ii ] ;
    j :
=  ii  *   2  ;
    
while  j  <=  len  do
    begin
        
if  ( j  <  len ) and ( heap[ j ] . val  >  heap[ j  +   1  ] . val ) then inc( j ) ;
        
if  num . val  >  heap[ j ] . val then
        begin
            heap[ ii ] :
=  heap[ j ] ;
            ii :
=  j ;
            j :
=  ii  *   2  ;
        end 
else   break  ;
    end ;
    heap[ ii ] :
=  num ;
end;

procedure dfs( x , y , max , deep : longint ) ;
var
    i , xx , yy : longint ;
begin
    u[ x , y ] :
=   false  ;
    
if  ( max  <  f[ x , y ] ) then f[ x , y ] : =  max ;
    
for  i : =   0  to  3   do
    begin
        xx :
=  x  +  dx[ i ] ; yy : =  y  +  dy[ i ] ;
        
if  ( xx  <=   0  ) or ( xx  >  n ) or ( yy  <=   0  ) or ( yy  >  m ) or ( not u[ xx , yy ] ) then  continue  ;
        
if  map[ xx , yy ]  <=  max then dfs( xx , yy , max , deep  +   1  )
        
else  begin
            
if  use[ xx , yy ] then
            begin
                ins( xx , yy , map[ xx , yy ] ) ;
                use[ xx , yy ] :
=   false  ;
            end ;
        end ;
    end ;
end ;

procedure floodfill( x : heaptype ) ;
var
    cici , i , a , b    : longint ;
begin
    
if  f[ x.x , x.y ]  =  zy then f[ x.x , x.y ] : =  map[ x.x , x.y ] ;
    dfs( x.x , x.y , f[ x.x , x.y ] , 
1  ) ;
end ;

procedure solve ;
var
    i , j       : longint ;
    now         : heaptype ;
begin
    fillchar( u , 
sizeof ( u ) ,  true  ) ;
    fillchar( use , 
sizeof ( use ) ,  true  ) ;
    len :
=   0  ;
    
for  i : =   1  to n  do
    begin
        
if  use[ i ,  1  ] then ins( i ,  1  , map[ i ,  1  ] ) ; use[ i ,  1  ] : =   false  ; f[ i ,  1  ] : =  map[ i ,  1  ] ;
        
if  use[ i , m ] then ins( i , m , map[ i , m ] ) ; use[ i , m ] : =   false  ; f[ i , m ] : =  map[ i , m ] ;
    end ;
    
for  i : =   1  to m  do
    begin
        
if  use[  1  , i ] then ins(  1  , i , map[  1  , i ] ) ; use[  1  , i ] : =   false  ; f[  1  , i ] : =  map[  1  , i ] ;
        
if  use[ n , i ] then ins( n , i , map[ n , i ] ) ; use[ n , i ] : =   false  ; f[ n , i ] : =  map[ n , i ] ;
    end ;
    
while  len  >   0   do
    begin
        now :
=  heap[  1  ] ; heap[  1  ] : =  heap[ len ] ;
        heap[ len ] . val :
=  maxlongint ; dec( len ) ;
        sort( 
1  ) ;
        floodfill( now ) ;
    end ;
end ;

procedure print ;
var
    i , j , ans : longint ;
begin
    ans :
=   0  ;
    
for  i : =   1  to n  do
        
for  j : =   1  to m  do  inc( ans , f[ i , j ]  -  map[ i , j ] ) ;
    writeln( ans ) ;
end ;

procedure main ;
begin
    init ;
    solve ;
    print ;
end ;

Begin
    main ;
end .

你可能感兴趣的:(POJ 2227 The Wedding Juicer FloodFill算法)