mayoko’s diary

プロコンとかいろいろ。

SRM646div1med:TheGridDivOne

問題:TopCoder Statistics - Problem Statement

解法:座標圧縮した後ダイクストラする。座標圧縮についてはよくわからなかったのでkmjpさんのコードを参考にさせていただきました。
以下ソースコード

struct Point {
    int y;
    int x;
    Point() {}
    Point(int y, int x) : y(y), x(x) {}
    bool operator<(const Point& rhs) const {
        return y <  rhs.y;
    }
};

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

const int MAXN = 200;
bool block[MAXN][MAXN];
int dist[MAXN][MAXN];

class TheGridDivOne {
public:
    int find(vector <int> x, vector <int> y, int k) {
        int n = x.size();
        /* 座標圧縮 */
        map<int, int> mx, my;
        mx[-1] = mx[0] = mx[1] = 0;
        my[-1] = my[0] = my[1] = 0;
        for (int i = 0; i < n; i++) {
            for (int d = -1; d <= 1; d++) {
                mx[x[i]+d] = 0;
                my[y[i]+d] = 0;
            }
        }
        vector<int> rx, ry;
        for (auto& el : mx) {
            el.second = rx.size();
            rx.push_back(el.first);
        }
        for (auto& el : my) {
            el.second = ry.size();
            ry.push_back(el.first);
        }
        memset(block, 0, sizeof(block));
        for (int i = 0; i < n; i++) {
            block[my[y[i]]][mx[x[i]]] = true;
        }
        rx.push_back(1<<30);
        ry.push_back(1<<30);
        /* dijkstra */
        for (int i = 0; i < MAXN; i++) for (int j = 0; j < MAXN; j++) dist[i][j] = 1<<30;
        Point start = Point(my[0], mx[0]);
        dist[start.y][start.x] = 0;
        priority_queue<pair<int, Point> > que;
        que.push(make_pair(0, start));
        while (!que.empty()) {
            auto now = que.top(); que.pop();
            Point p = now.second;
            int d = -now.first;
            if (d != dist[p.y][p.x]) continue;
            for (int i = 0; i < 4; i++) {
                int ny = p.y+dy[i], nx = p.x+dx[i];
                if (ny < 0 || ny >= ry.size() || nx < 0 || nx >= rx.size() || block[ny][nx]) continue;
                int distx = abs(rx[nx]-rx[p.x]), disty = abs(ry[ny]-ry[p.y]);
                if (d+distx+disty > k || dist[ny][nx] <= d+distx+disty) continue;
                dist[ny][nx] = d+distx+disty;
                que.push(make_pair(-dist[ny][nx], Point(ny, nx)));
            }
        }
        int ans = 0;
        for (int i = 0; i < ry.size(); i++) for (int j = 0; j < rx.size(); j++) {
            int rest = k-dist[i][j];
            if (rest < 0) continue;
            ans = max(ans, min(rx[j+1]-1, rx[j]+rest));
        }
        return ans;
    }
};