ICPC国内予選2010

24位. 多分去年とあまり変わらない. まさに「まるで成長してない…」


前日夜中に体温が38度を突破. 一時は出場できないかと冷や汗をかいたが, 当日昼過ぎまで寝た結果, 体調が戻ったので参加することに. ちなみに私以外の2人はそれぞれ初対面なので, 出れて良かった.*1


開始後はA, Bを解いたあとCをメンバーにバトンタッチ. その後Dに取りかかるがバグが取りきれず終了. 実装力が足りないなぁと思う. 夏休みはちまちま問題を解いていきたい...


ちなみに以下は後日解いたD. 見直すとクズっぽさが半端無い. 下から適当にBFSでブロック探索(重心と下のブロックの情報も一緒に)→木を作成→再帰で計算 みたいな流れ. しかし本当長いなこのコード.................................

#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;

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

vector<vector<int> > lnk;

struct Node {
    int x, y, c;
    int  xl, xr;
    Node(int x, int y, int c, int xl, int xr) : x(x), y(y), c(c), xl(xl), xr(xr) {}
};

struct SPoint {
    int x, y, p, pn;
    SPoint(int x, int y, int p, int pn) : x(x), y(y), p(p), pn(pn) {}
};

struct Piece {
    int n;
    double x;
    int p;
    int xl, xr;
    Piece(int n, double x, int p, int xl, int xr) : n(n), x(x), p(p), xl(xl), xr(xr) {}
};

bool f(int);

vector<Piece> pieces;

int main(int argc, char *argv[])
{
    bool visited[60][10];
    int w, h, m[60][10];
    char c;
    while (scanf("%d %d ", &w, &h), w|h) {
        memset(visited, false, sizeof(visited));

        // reading
        for (int i=h-1; i>=0; --i) {
            for (int j=0; j<w; ++j) {
                scanf("%c ", &c);
                if (c == '.') {
                    m[i][j] = 0;
                } else {
                    m[i][j] = c - '0';
                }
                visited[i][j] = false;
            }
        }

        // search starting point
        int sx, sy = 0;
        for (int i=0; i<w; ++i) {
            if (m[0][i]) {
                sx = i;
                sy = 0;
                break;
            }
        }

        pieces.clear();
        lnk.clear();


        queue<SPoint> SQ;
        SQ.push(SPoint(sx, sy, -1, -1));
        int pn = 0;
        while (!SQ.empty()) {
            SPoint sp = SQ.front();
            SQ.pop();
            if (visited[sp.y][sp.x]) {
                continue;
            }

            double gx = 0;
            queue<Node> NQ;
            NQ.push(Node(sp.x, sp.y, m[sp.y][sp.x], sp.x, sp.x+1));
            int xl = sp.x, xr = sp.x+1;
            while (!NQ.empty()) {
                Node n = NQ.front();
                NQ.pop();
                if (visited[n.y][n.x]) {
                    continue;
                }

                visited[n.y][n.x] = true;
                gx += n.x + 0.5;

                if (n.y+1 < h && m[n.y+1][n.x] != n.c &&
                    !visited[n.y+1][n.x] && m[n.y+1][n.x]) {
                    SQ.push(SPoint(n.x, n.y+1, sp.p, pn));
                }

                if (n.y-1 >= 0 && m[n.y-1][n.x] &&
                    m[n.y][n.x] != m[n.y-1][n.x]) {
                        xl = min(xl, n.x);
                        xr = max(xr, n.x+1);
                }

                for (int i=0; i<4; ++i) {
                    int nx = n.x + dx[i];
                    int ny = n.y + dy[i];
                    if (nx < 0 || nx >= w || ny < 0 || ny >= h ||
                        visited[ny][nx] || m[ny][nx] != n.c) {
                        continue;
                    }
                    NQ.push(Node(nx, ny, n.c, xl, xr));
                }
            }
            gx /= 4.0;
            pieces.push_back(Piece(1, gx, sp.pn, xl, xr));
            ++pn;
        }

        bool onGround = false;
        for (int i=0; i<w; ++i) {
            if (m[0][i] && !onGround) {
                pieces[0].xl = i;
                onGround = true;
            } else if (onGround && !m[0][i]) {
                pieces[0].xr = i;
                break;
            } else if (onGround && i == w-1) {
                pieces[0].xr = i+1;
            }
        }

        lnk.clear();
        lnk.resize(pieces.size());

        for (int i=0; i<(int)pieces.size(); ++i) {
            if (pieces[i].p >= 0) {
                lnk[pieces[i].p].push_back(i);
            }
        }
        if (f(0)) {
            printf("STABLE\n");
        } else {
            printf("UNSTABLE\n");
        }
    }
    return 0;
}

bool f(int i) {
    Piece p = pieces[i];
    int xl =p.xl;
    int xr = p.xr;
    if (lnk[i].size() == 0) {
        return xl < p.x && p.x < xr;
    }

    int j, n = 0;
    double x = 0, gx=0;
    bool ret = true;
    for (j=0; j<(int)lnk[i].size(); ++j) {
        ret = ret && f(lnk[i][j]);
        n += pieces[lnk[i][j]].n;
        x += pieces[lnk[i][j]].x;
        gx += pieces[lnk[i][j]].x*pieces[lnk[i][j]].n;
    }
    pieces[i].x = (gx+pieces[i].x)/(n+1);
    pieces[i].n = n+1;
    return ret && xl < pieces[i].x && pieces[i].x < xr;
}

ほ、本番の時に焦ったやつを直した…とは言え酷いにも程がある--); 精進したい

*1:この時点で突っ込み所満載のチームである