pku 1175 Starry Night

pku 1175 Starry Night
#include  < stdio.h >
#include 
< stdlib.h >
#include 
< assert.h >

#define  NAME "starry"
/*  MAXSTAR is the largest a cluster can be  */
#define  MAXSTAR 160

/*  the board  */
char  board[ 100 ][ 100 ];
int  w, h;

/*  clusters already lettered  */
int  stars[ 26 ][MAXSTAR];  /*  stars are stored as xval + yval*1000  */
int  count[ 26 ];  /*  number of stars  */
int  size[ 26 ][ 2 ];  /*  the x & y dimensions  */
int  nstart;  /*  number of clusters  */

/*  the current cluster  */
int  current[MAXSTAR][ 2 ];  /*  y, x  */
int  ncurrent;  /*  number of stars in current cluster  */

/*  int_comp is integer comparison, used for bsearch and qsort  */
int
int_comp(
const   void   * pa,  const   void   * pb)
 {
  
int  a  =   * ( int * )pa;
  
int  b  =   * ( int * )pb;
  
if  (a  >  b)  return   1 ;
  
else   if  (a  <  b)  return   - 1 ;
  
else   return   0 ;
 }

/*  find the boundary (in my,mx,My, and Mx.. m is minimum, M is maximum  */
/*  also fills in current  */
int
find_boundary(
int  y,  int  x,  int   * my,  int   * mx,  int   * My,  int   * Mx)
 {
  
int  rv  =   0 ;
  
if  (board[y][x]  !=   ' 1 ' return   0 /*  not a star or already visited  */
  rv
++ /*  one more star  */
  board[y][x] 
=   ' 2 ' /*  mark as visited  */

  
/*  put in current cluster  */
  current[ncurrent][
0 =  y;
  current[ncurrent][
1 =  x;
  ncurrent
++ ;

  
/*  update boundary  */
  
if  (y  <   * my)  * my  =  y;
  
if  (y  >   * My)  * My  =  y;
  
if  (x  <   * mx)  * mx  =  x;
  
if  (x  >   * Mx)  * Mx  =  x;

  
/*  check all adjacent stars  */
  
if  (x  >   0
   {
    x
-- ;
    rv 
+=  find_boundary(y, x, my, mx, My, Mx);
    
if  (y  >   0 ) rv  +=  find_boundary(y - 1 , x, my, mx, My, Mx);
    
if  (y + 1   <  h) rv  +=  find_boundary(y + 1 , x, my, mx, My, Mx);
    x
++ ;
   }
  
if  (y  >   0 ) rv  +=  find_boundary(y - 1 , x, my, mx, My, Mx);
  
if  (y + 1   <  h) rv  +=  find_boundary(y + 1 , x, my, mx, My, Mx);
  
if  (x + 1   <  w)
   {
    x
++ ;
    rv 
+=  find_boundary(y, x, my, mx, My, Mx);
    
if  (y  >   0 ) rv  +=  find_boundary(y - 1 , x, my, mx, My, Mx);
    
if  (y + 1   <  h) rv  +=  find_boundary(y + 1 , x, my, mx, My, Mx);
    x
-- ;
   }
  
return  rv;
 }

/*  this is a very basic flood fillfill ch everywhere there's not a '0'  */
void
mark_shape(
int  y,  int  x,  char  ch)
 {
  
if  (board[y][x]  ==  ch)  return /*  done already  */
  
if  (board[y][x]  ==   ' 0 ' return /*  nothing to do  */

  board[y][x] 
=  ch;

  
/*  recurse on all boundary stars  */
  
if  (x  >   0
   {
    x
-- ;
    mark_shape(y, x, ch);
    
if  (y  >   0 ) mark_shape(y - 1 , x, ch);
    
if  (y + 1   <  h) mark_shape(y + 1 , x, ch);
    x
++ ;
   }
  
if  (y  >   0 ) mark_shape(y - 1 , x, ch);
  
if  (y + 1   <  h) mark_shape(y + 1 , x, ch);
  
if  (x + 1   <  w) 
   {
    x
++ ;
    mark_shape(y, x, ch);
    
if  (y  >   0 ) mark_shape(y - 1 , x, ch);
    
if  (y + 1   <  h) mark_shape(y + 1 , x, ch);
   }
 }

/*  is shape id the same as the current shape  */
/*  specify the orientation with dy/dx and by/bx  */
/*  dy/dx is the difference value to associate with y and x changes  */
/*  by/bx is the upper right corner of the bounding box with respect
   to the current orientation 
*/
/*  NOTE: assumes that the number of stars are the same  */
int
check_shape(
int  id,  int  dy,  int  dx,  int  by,  int  bx)
 {
  
int  lv;
  
int  pval;

  
for  (lv  =   0 ; lv  <  ncurrent; lv ++ )
   {
    pval 
=  (current[lv][ 0 ] - by) * dy  +  (current[lv][ 1 ] - bx) * dx;
    
if  ( ! bsearch( & pval, stars[id], count[id],  sizeof (stars[id][ 0 ]), int_comp))
      
return   0 /*  found a star that didn't match  */
   }
  
return   1 ;
 }

/*  we found a star here, make it a cluster  */
void
fix_board(
int  y,  int  x)
 {
  
int  mx, my, Mx, My;
  
int  cnt;
  
int  lv;
  
int  pw, ph;
  
int  f;

/*  gather the cluster information  */
  mx 
=  Mx  =  x;
  my 
=  My  =  y;

  ncurrent 
=   0 ;
  cnt 
=  find_boundary(y, x,  & my,  & mx,  & My,  & Mx);

  pw 
=  Mx  -  mx  +   1 ;
  ph 
=  My  -  my  +   1 ;

  f 
=   0 ;
  
/*  check each cluster  */
  
for  (lv  =   0 ; lv  <  nstart; lv ++ )
    
if  (cnt  ==  count[lv])  /*  the cluster must have the same # of stars  */
     {
      
if  (pw  ==  size[lv][ 1 &&  ph  ==  size[lv][ 0 ])
       { 
/*  the bounding box sizes match  */
 f 
+=  check_shape(lv,  1000 1 , my, mx);
 f 
+=  check_shape(lv,  1000 - 1 , my, Mx);
 f 
+=  check_shape(lv,  - 1000 1 , My, mx);
 f 
+=  check_shape(lv,  - 1000 - 1 , My, Mx);
       }
      
if  (pw  ==  size[lv][ 0 &&  ph  ==  size[lv][ 1 ])
       { 
/*  the bounding box sizes match  */
 f 
+=  check_shape(lv,  1 1000 , my, mx);
 f 
+=  check_shape(lv,  1 - 1000 , my, Mx);
 f 
+=  check_shape(lv,  - 1 1000 , My, mx);
 f 
+=  check_shape(lv,  - 1 - 1000 , My, Mx);
       }
      
if  (f)  break ;
     }
  
if  (f) mark_shape(y, x,  ' a '   +  lv);  /*  found match  */
  
else  {  /*  new cluster!  */
    count[nstart] 
=   0 ;
    mark_shape(y, x, 
' a '   +  nstart);
    
for  (lv  =   0 ; lv  <  ncurrent; lv ++ )
      stars[nstart][lv] 
=  (current[lv][ 0 ] - my) * 1000   +  (current[lv][ 1 ] - mx);
    count[nstart] 
=  ncurrent;
    
/*  we need the stars in increasing order  */
    qsort(stars[nstart], count[nstart], 
sizeof (stars[nstart][ 0 ]), int_comp);
    size[nstart][
0 =  ph;
    size[nstart][
1 =  pw;
    nstart
++ ;
   }
 }

int
main(
int  argc,  char   ** argv)
 {
  
// FILE *fin, *fout;
   int  lv, lv2;

  
// fin = fopen(NAME ".in", "r");
  
// fout = fopen(NAME ".out", "w");
  
// assert(fin);
 
//  assert(fout);

/*  read in the data  */
  scanf (
" %d %d " & w,  & h);

  
for  (lv  =   0 ; lv  <  h; lv ++ ) scanf ( " %s " , board[lv]);
 
//  fclose(fin);

/*  everywhere there's a star not in a cluster, make it into one  */
  
for  (lv  =   0 ; lv  <  h; lv ++ )
    
for  (lv2  =   0 ; lv2  <  w; lv2 ++ )
      
if  (board[lv][lv2]  ==   ' 1 ' )
        fix_board(lv, lv2);

/*  output data  */
  
for  (lv  =   0 ; lv  <  h; lv ++ )
   {
    printf (
" %c " , board[lv][ 0 ]);
    
for  (lv2  =   1 ; lv2  <  w; lv2 ++ )
      printf (
" %c " , board[lv][lv2]);
     printf ( 
" \n " );
   }

 
//  fclose(fout);
   return   0 ;
 }


修改 usaco 分析的代码
floodfill找出1的区域  在和以前找出的区域 旋转匹配 如果找到则用前面那个编号 找不到则编号加1

你可能感兴趣的:(pku 1175 Starry Night)