結果

問題 No.348 カゴメカゴメ
ユーザー motimoti
提出日時 2016-03-23 23:24:05
言語 C++11
(gcc 11.4.0)
結果
AC  
実行時間 57 ms / 2,000 ms
コード長 3,429 bytes
コンパイル時間 1,770 ms
コンパイル使用メモリ 184,152 KB
実行使用メモリ 10,476 KB
最終ジャッジ日時 2024-10-01 21:40:44
合計ジャッジ時間 4,611 ms
ジャッジサーバーID
(参考情報)
judge5 / judge2
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 46 ms
8,836 KB
testcase_01 AC 4 ms
6,820 KB
testcase_02 AC 56 ms
10,476 KB
testcase_03 AC 47 ms
8,704 KB
testcase_04 AC 4 ms
6,912 KB
testcase_05 AC 4 ms
6,912 KB
testcase_06 AC 3 ms
6,912 KB
testcase_07 AC 4 ms
6,820 KB
testcase_08 AC 4 ms
6,820 KB
testcase_09 AC 3 ms
6,912 KB
testcase_10 AC 3 ms
7,040 KB
testcase_11 AC 4 ms
6,816 KB
testcase_12 AC 5 ms
6,988 KB
testcase_13 AC 3 ms
6,856 KB
testcase_14 AC 3 ms
6,912 KB
testcase_15 AC 46 ms
8,900 KB
testcase_16 AC 4 ms
6,856 KB
testcase_17 AC 3 ms
6,856 KB
testcase_18 AC 4 ms
6,912 KB
testcase_19 AC 4 ms
7,040 KB
testcase_20 AC 3 ms
6,820 KB
testcase_21 AC 3 ms
6,784 KB
testcase_22 AC 3 ms
6,912 KB
testcase_23 AC 54 ms
9,088 KB
testcase_24 AC 57 ms
9,088 KB
testcase_25 AC 55 ms
8,984 KB
testcase_26 AC 55 ms
9,036 KB
testcase_27 AC 54 ms
9,044 KB
testcase_28 AC 56 ms
9,088 KB
testcase_29 AC 53 ms
9,088 KB
testcase_30 AC 53 ms
9,088 KB
testcase_31 AC 55 ms
8,960 KB
testcase_32 AC 54 ms
9,088 KB
testcase_33 AC 8 ms
7,112 KB
testcase_34 AC 8 ms
7,168 KB
testcase_35 AC 9 ms
7,128 KB
testcase_36 AC 8 ms
7,116 KB
testcase_37 AC 7 ms
7,168 KB
testcase_38 AC 8 ms
7,040 KB
testcase_39 AC 9 ms
7,040 KB
testcase_40 AC 8 ms
7,168 KB
testcase_41 AC 7 ms
7,168 KB
testcase_42 AC 7 ms
6,948 KB
testcase_43 AC 4 ms
6,912 KB
testcase_44 AC 5 ms
6,856 KB
testcase_45 AC 4 ms
6,876 KB
testcase_46 AC 4 ms
6,912 KB
testcase_47 AC 4 ms
7,040 KB
testcase_48 AC 4 ms
6,912 KB
testcase_49 AC 5 ms
6,816 KB
testcase_50 AC 4 ms
6,852 KB
testcase_51 AC 5 ms
6,820 KB
testcase_52 AC 5 ms
6,820 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>

using namespace std;

#define REP(i,a,b) for(int i=a;i<(int)b;i++)
#define rep(i,n) REP(i,0,n)
#define minus(c) memset(c, -1, sizeof c)

const int Max = 110890;
int dx[] = {-1,0,1,0,-1,1,1,-1};
int dy[] = {0,-1,0,1,-1,-1,1,1};
char VisMark = ' ';
char RingMark = 'o';

int N, M;
vector<string> G;
int ring_lens[Max];
vector<int> tree[Max]; // to, cost

template<class T> constexpr bool in_range(T y, T x, T H, T W) { return 0<=y&&y<H&&0<=x&&x<W; }

void make_tree() {

  auto get_ring_len = [](int sy, int sx) {
    int ret = 1;
    queue<pair<int, int>> q;
    q.emplace(sy, sx);
    G[sy][sx] = RingMark;
    while(!q.empty()) {
      int y, x; tie(y, x) = q.front(); q.pop();
      rep(i, 8) { // 'x'は8方向
        int ny = y + dy[i], nx = x + dx[i];
        if(!in_range(ny, nx, N, M)) { continue; }
        if(G[ny][nx] != 'x') { continue; }
        G[ny][nx] = RingMark;
        ret ++;
        q.emplace(ny, nx);
      }
    }
    return ret;
  };

  auto get_next_depth_ring = [&](int sy, int sx) {
    vector<tuple<int, int, int>> ret;
    queue<pair<int, int>> q;
    q.emplace(sy, sx);
    G[sy][sx] = VisMark;
    // 次の深さの輪を見つけるために、同じ深さ輪の間の '.' を訪れるBFS
    while(!q.empty()) {
      int y, x; tie(y, x) = q.front(); q.pop();
      rep(i, 4) { // 4方向で輪を跨がずに'.'を消す
        int ny = y + dy[i], nx = x + dx[i];
        if(!in_range(ny, nx, N, M)) { continue; }
        // 同じ深さの輪の間の '.'
        if(G[ny][nx] == '.') {
          G[ny][nx] = VisMark;
          q.emplace(ny, nx);
        }
        // 'x' は輪の要素なので、一つ見つけてあとは塗りつぶす
        if(G[ny][nx] == 'x') {
          ret.emplace_back(ny, nx, get_ring_len(ny, nx));
        }
      }
    }
    return std::move(ret);
  };

  // 同じ深さの木の葉が左から並ぶ (y, x, ノード番号)
  // '.'が連続する領域をノードと捉える
  queue<tuple<int, int, int>> leaves;
  leaves.emplace(0, 0, 0);
  int nextch = 1;
  // BFS木を作る
  while(!leaves.empty()) {
    int ly, lx, leaf; tie(ly, lx, leaf) = leaves.front(); leaves.pop();
    auto ring_nodes = get_next_depth_ring(ly, lx);
    for(auto && e: ring_nodes) {
      int y, x, len; tie(y, x, len) = e;
      tree[leaf].emplace_back(nextch);
      ring_lens[nextch] = len;
      rep(k, 8) { // 8方向で輪を跨ぐ'.'を見つける
        int ny = y + dy[k], nx = x + dx[k];
        if(!in_range(ny, nx, N, M)) { continue; }
        if(G[ny][nx] == '.') {
          leaves.emplace(ny, nx, nextch);
          break;
        }
      }
      nextch++;
    }
  }
}

int dp[Max][2];

int rec(int curr, bool par_used = true) {
  auto& ret = dp[curr][par_used];
  if(ret + 1) { return ret; }
  if(tree[curr].empty()) { return ret = par_used ? 0 : ring_lens[curr]; }
  ret = 0;
  if(par_used) {
    rep(i, tree[curr].size()) { ret += rec(tree[curr][i], false); }
  }
  else {
    int r1 = ring_lens[curr];
    for(auto && e: tree[curr]) { r1 += rec(e, true); }
    int r2 = 0;
    for(auto && e: tree[curr]) { r2 += rec(e, false); }
    ret = max(r1, r2);
  }
  return ret;
}

int main() {
  cin >> N >> M;
  N += 2, M += 2;
  G.resize(N);
  G[0] = string(M, '.');
  REP(i, 1, N-1) {
    cin >> G[i];
    G[i] = "." + G[i] + ".";
  }
  G.back() = string(M, '.');
  make_tree();
  minus(dp);
  cout << rec(0) << endl;
  return 0;
}
0