SRM465

追記(3/27):600解いてSystemTest通した

250の問題を勘違いしていたせいで時間かかりまくり。全ての(x,y)に四角形を置くと思ってた…。2つかよ…。死にたい。誰か俺を殺せ。

ということでスコアは 1452->1423 と減少。600の方は最小カットという噂を聞いた。あとでリベンジするかな。

  • > リベンジした。以下コード。

最大流で、エドモンズ・カープ。Dinic実装したことないですごめんなさい…。
それはそうとコード無駄に長い気がするので、あとで他人のを参考にするべきですね...。
…あとちゃんとtypedefしろよ > 俺

class GreenWarfare {
public:
    int calc_energy(int x1, int y1, int x2, int y2) {
        return (int)(pow(x1-x2, 2.0)+pow(y1-y2, 2.0));
    }

    int max_flow(vector<vector<int> >& edges, vector<vector<int> >& caps, int s, int t) {
        int f = 0, n = edges.size();
        vector<vector<int> > flow(n, vector<int>(n, 0));
        while (1) {
            // BFS
            queue<int> Q; Q.push(s);
            vector<int> prev(n, -1); prev[s] = s;
            while (!Q.empty() && prev[t] < 0) {
                int u = Q.front(); Q.pop();
                for (int i=0; i<static_cast<int>(edges[u].size()); ++i) {
                    int dst = edges[u][i];
                    if (prev[dst] < 0 && caps[u][dst]-flow[u][dst] > 0) {
                        prev[dst] = u;
                        Q.push(dst);
                    }
                }
            }
            if (prev[t] < 0) return f;
            int inc = INT_MAX;
            for (int i=t; prev[i] != i; i = prev[i]) {
                inc = min(inc, caps[prev[i]][i]-flow[prev[i]][i]);
            }
            for (int i=t; prev[i] != i; i = prev[i]) {
                flow[prev[i]][i] += inc; flow[i][prev[i]] -= inc;
            }
            f += inc;
        }
        return f;
    }

    void add(vector<vector<int> >& edges, vector<vector<int> >& costs, int s, int t, int c) {
        edges[s].push_back(t);
        costs[s][t] = c;
        edges[t].push_back(s);
        costs[t][s] = 0;
    }

    int minimumEnergyCost(vector <int> canonX, vector <int> canonY, vector <int> baseX, vector <int> baseY, vector <int> plantX, vector <int> plantY, int energySupplyRadius) {
        int s = 0, t = baseX.size()+plantX.size()+1;
        int base_offset = 1, plant_offset = 1+baseX.size();
        int R2 = energySupplyRadius*energySupplyRadius;

        vector<vector<int> > edges(t+1);
        vector<vector<int> > costs(t+1, vector<int>(t+1, 0));

        for (int i=0; i<static_cast<int>(baseX.size()); ++i) {
            // s -> base
            int e = INT_MAX;
            for (int j=0; j<static_cast<int>(canonX.size()); ++j) {
                e = min(e, calc_energy(baseX[i], baseY[i], canonX[j], canonY[j]));
            }
            add(edges, costs, s, base_offset+i, e);

            // base -> plant|t
            bool added = false;
            for (int j=0; j<static_cast<int>(plantX.size()); ++j) {
                if (calc_energy(baseX[i], baseY[i], plantX[j], plantY[j]) <= R2) {
                    added = true;
                    add(edges, costs, base_offset+i, plant_offset+j, INT_MAX);
                }
            }
            if (!added) {
                add(edges, costs, base_offset+i, t, INT_MAX);
            }
        }

        for (int i=0; i<static_cast<int>(plantX.size()); ++i) {
            // plant -> t
            int e = INT_MAX;
            for (int j=0; j<static_cast<int>(canonX.size()); ++j) {
                e = min(e, calc_energy(plantX[i], plantY[i], canonX[j], canonY[j]));
            }
            add(edges, costs, plant_offset+i, t, e);
        }

        return max_flow(edges, costs, s, t);
    }
};