#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 fill fill ch everywhere there's not a '0' */
fill 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
	
posted on 2008-10-11 15:58 
爬 阅读(449) 
评论(0)  编辑 收藏 引用  所属分类: 
pku