AOJ : 1211 - Trapezoids

問題概要

http://rose.u-aizu.ac.jp/onlinejudge/ProblemSet/description.jsp?id=1211


アスタリスクによって構成された台形を含む文字列が入力される。
各台形の面積を計算し、面積の値と、その面積の台形がいくつあったかをカウントして出力する。

入力される台形は、次のことを満たしている。

  • 台形と台形の間には、必ず1文字間隔があく
  • 台形の上底と下底は、必ずx軸方向に平行
  • 台形の両サイドの辺の傾きは、90度か45度

アルゴリズム

台形の始点のアスタリスクを決めて、その地点から再帰を使って台形を辿る。
再帰で辿っていく際に、同時に台形の頂点4つを決める処理を行う。
あとは、4点の情報をもとに、台形の面積を計算する。

プログラム

#include <stdio.h>
#include <string.h>

#define REP(i,n,m) for(i=n;i<m;i++)
#define rep(i,n) REP(i,0,n)

int h,w;
int tx[4],ty[4];
int area[80010];
char t[1002][82];

int dx[] = {0,-1,-1,-1,0,1,1,1};
int dy[] = {-1,-1,0,1,1,1,0,-1};

void updatePoint(int x,int y){
  if(ty[0] > y){
    ty[0] = ty[3] = y;
    tx[0] = tx[3] = x;
  }
  else if(ty[0] == y){
    if(tx[0] > x) tx[0] = x;
    else if(tx[3] < x) tx[3] = x;
  }

  if(ty[1] < y){
    ty[1] = ty[2] = y;
    tx[1] = tx[2] = x;
  }
  else if(ty[1] == y){
    if(tx[1] > x) tx[1] = x;
    else if(tx[2] < x) tx[2] = x;
  }
}

void solve(int x,int y,int d){
  int i,nx,ny;

  t[y][x] = ' ';
  updatePoint(x,y);

  rep(i,8){
    nx = x + dx[i];
    ny = y + dy[i];

    if(nx>=0 && nx<w && ny>=0 && ny<h && t[ny][nx]=='*'){
      solve(nx,ny,i);
    }
  }
}

int main(void){
  int set,i,j;
  char s[12];
  w = 80;

  for(set=0;fgets(s,12,stdin);set++){
    h = atoi(s);
    if(h == 0) break;
    if(set != 0) printf("----------\n");

    memset(t,' ',sizeof(t));
    memset(area,0,sizeof(area));

    rep(i,h) fgets(t[i],w,stdin);

    rep(i,h) rep(j,w) if(t[i][j] == '*') {
      tx[0] = tx[1] = w;
      tx[2] = tx[3] = 0;
      ty[0] = ty[3] = h;
      ty[1] = ty[2] = 0;

      solve(j,i,-1);

      area[((tx[3]-tx[0]+1)+(tx[2]-tx[1]+1))*(ty[1]-ty[0]+1)/2]++;
    }

    rep(i,80010) if(area[i] > 0) {
      printf("%d %d\n",i,area[i]);
    }
  }

  return 0;
}