読者です 読者をやめる 読者になる 読者になる

mayoko’s diary

プロコンとかいろいろ。

AOJ 1168: ぐらぐら

これ全然むずかしくないし 250 くらいで良いのでは…?

解法

言われたとおりやるだけです。

ブロックを上から調べていき, それが地面にどれだけくっついているのかを調べます。
また, そのブロックの上に乗っかっているブロックを全部調べます。

で, x 軸方向の重心が条件を満たすかを調べるだけです。
double 型だと気持ち悪いので, x 軸方向は 2 倍しておくと全部整数で処理できます。

int H, W;
string board[100];

vector<pii> getPos(char c, int sy, int sx) {
    vector<pii> ret;
    queue<int> que;
    que.push(sy); que.push(sx);
    ret.emplace_back(sy, sx);
    while (!que.empty()) {
        int y = que.front(); que.pop();
        int x = que.front(); que.pop();
        for (int i = 0; i < 4; i++) {
            int ny = y+dy[i];
            int nx = x+dx[i];
            if (ny < 0 || ny >= H || nx < 0 || nx >= W) continue;
            if (board[ny][nx] == c && find(ret.begin(), ret.end(), pii(ny, nx)) == ret.end()) {
                que.push(ny); que.push(nx);
                ret.emplace_back(ny, nx);
            }
        }
    }
    return ret;
}

bool ok() {
    for (int y = 0; y < H; y++) for (int x = 0; x < W; x++) {
        // c を探せ
        char c = board[y][x];
        if (c == '.') continue;
        vector<pii> ps = getPos(c, y, x);
        int xl = 100, xr = -1;
        for (pii p : ps) {
            int y = p.first, x = p.second;
            if (y == H-1) {
                xl = min(xl, 2*x);
                xr = max(xr, 2*x+2);
            } else {
                int ny = y+1;
                if (board[ny][x] != '.' && board[ny][x] != c) {
                    xl = min(xl, 2*x);
                    xr = max(xr, 2*x+2);
                }
            }
        }
        // cerr << c << " : " << xl << "  " << xr << endl;
        // ps に支えられているのを探せ
        vector<pii> up = ps;
        while (1) {
            bool finish = true;
            for (pii p : up) {
                int y = p.first, x = p.second;
                if (y==0) continue;
                char tmp = board[y-1][x];
                if (tmp == '.') continue;
                vector<pii> cs = getPos(tmp, y-1, x);
                assert(!cs.empty());
                if (find(up.begin(), up.end(), cs[0]) == up.end()) {
                    finish = false;
                    for (pii pp : cs) up.push_back(pp);
                    break;
                }
            }
            if (finish) break;
        }
        int sum = 0;
        for (pii p : up) {
            sum += 2*p.second+1;
        }
        if (sum <= xl * up.size() || sum >= xr * up.size()) return false;
    }
    return true;
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    while (cin >> W >> H) {
        if (H==0 && W==0) break;
        for (int i = 0; i < H; i++) cin >> board[i];
        if (ok()) cout << "STABLE" << endl;
        else cout << "UNSTABLE" << endl;
    }
    return 0;
}