AOJ 2206 Compile

ぷよぷよです.
綺麗じゃない気がするけど,とりあえず通ったのでよし.

以下に注意.

  • 同時消しあり
  • 4つ以上くっついたブロックが消えるとき,隣にお邪魔があったら一緒に消える

上記を見落としていたこともあり,2時間半かかった….

// AOJ 2206 accepted 2012-01-09
// お邪魔を消すこと,同時消しの考慮を忘れていた.(問題文をちゃんと読んでなかった)
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
using namespace std;
const int COLS = 6;
const int ROWS = 12;
const char CLEAR = '*';
char  memo_board[ROWS][COLS];

// 確認用
void print(char board[ROWS][COLS]){
  for (int y=0; y<ROWS; y++) {
    printf("%2d ",y);
    for (int x=0; x<COLS; x++) {
      cout << board[y][x];
    }
    cout << endl;
  }
}

// つなげてみる
int connect(char block, int x, int y, int count) {
  int ret = count;
  for (int dx=-1; dx<=1; dx++) {
    for (int dy=-1; dy<=1; dy++) {
      if (dx == dy) continue;
      if (dx * dy != 0) continue;
      if (0 <= x + dx && x + dx < COLS && 0 <= y + dy && y + dy < ROWS) {
        if (memo_board[y+dy][x+dx] == block) {
          memo_board[y+dy][x+dx] = CLEAR;
          ret += connect(block, x+dx, y+dy, 1);
        }
        else if (memo_board[y+dy][x+dx] == 'O') { //お邪魔
          memo_board[y+dy][x+dx] = CLEAR;          
        }
      }
    }
  }
  return ret;
}

// '*'になっているブロックを消す
void clear(char board[ROWS][COLS]) {  
  //消す
  for (int x=0; x<COLS; x++) {
    // 新しいx列目を生成
    vector<char> newRow;
    for (int y=ROWS-1; y>=0; y--) {
      if (board[y][x] == CLEAR) continue;
      newRow.push_back(board[y][x]);
    }
    for (int y=newRow.size(); y<ROWS; y++) {
      newRow.push_back('.');
    }
    
    // x列目に適用
    for (int y=ROWS-1; y>=0; y--) {
      board[y][x] = newRow[ROWS-1-y];
    }
  }

}

int main() {
  int n = 0;
  cin >> n;
  for (int i=0; i<n; i++) {
    char  board[ROWS][COLS];
    // input board
    for (int y=0; y<ROWS; y++) {
      for (int x=0; x<COLS; x++) {
        cin >> board[y][x];
      }
    }
    // start
    int rensa = 0;
    bool canClear;
    do {
      canClear = false;
      for (int startX=0; startX<COLS; startX++) {
        for (int startY=ROWS-1; startY>=0; startY--) {
          //退避
          memcpy(memo_board, board, sizeof(board));
          //つなげてみて,4つ以上つながるなら消す
          char block = board[startY][startX];
          if (block == 'O' || block == '.' || block == CLEAR) continue;
          memo_board[startY][startX] = CLEAR;
          if (connect(block, startX, startY, 1) >= 4) {
            //print(memo_board);
            memcpy(board, memo_board, sizeof(board));
            canClear = true;
          }
        }
      }
      // 可能なら消す
      if (canClear) {
        clear(board);
        rensa++;
      }      
    } while (canClear);
    
    cout << rensa << endl;
  }
  return 0;
}