ICPC 2013 アジア地区予選 参加記 (競技について)

競技以外についてはこちら

チームに割り当てられた端末のホームディレクトリ以下のsouvenirフォルダに入れたファイルはおみやげとしてメールで送られてくるというシステムでした。 先ほど届いたので提出コードを貼り付けます

A

  • solve(n,k,s) = solve(n-1,k-1,s-n) + solve(n-1,k,s) みたいな漸化式のほうが良さそう (DPの練習的には)
  • もっと言えば for(int b = 0; b < (1 << n); b++) if(__builtin_popcount(b) == k) { .. } みたいなほうが良さそう (実装の容易さ的には)
#include <bits/stdc++.h>
using namespace std;

int solve(int n, int k, int s) {
    if(k == 0 && s == 0) return 1;
    int res = 0;
    for(int i = 1; i <= n; i++) {
        res += solve(i - 1, k - 1, s - i);
    }
    return res;
}

int main() {
    while(true) {
        int N, K, S; cin >> N >> K >> S;
        if(N == 0 && K == 0 && S == 0) break;
        cout << solve(N, K, S) << endl;
    }
}

B

#include <bits/stdc++.h>
using namespace std;

#define DEBUG(x) cerr << #x << " = " << x << endl

int main() {
    while(true) {
        int N, L; cin >> N >> L;
        if(N == 0 && L == 0) break;
        vector<int> pos(N);
        // L=-1, R=1
        vector<int> dir(N);
        for(int i = 0; i < N; i++) {
            int p; char d;
            cin >> d >> p;
            pos[i] = p;
            dir[i] = (d == 'R') ? 1 : -1;
        }
        int last = 0;
        int lastsecond = 0;
        int second = 0;
        int lastPos = (int)1e9;
        vector<int> live(N, 1);
        while(true) {
            second++;
            vector<int> on(L + 1, 0);
            for(int i = 0; i < N; i++) {
                if(live[i]) {
                    pos[i] += dir[i];
                    on[pos[i]]++;
                }
            }
            for(int i = 0; i < N; i++) {
                if(live[i]) {
                    if(on[pos[i]] >= 2) {
                        dir[i] *= -1;
                    }
                }
            }
            for(int i = 0; i < N; i++) {
                if(live[i]) {
                    if(pos[i] == 0 || pos[i] == L) {
                        live[i] = 0;
                        if(second == lastsecond) {
                            if(pos[i] < lastPos) {
                                last = i;
                                lastsecond = second;
                                lastPos = pos[i];
                            }
                        }
                        else {
                            last = i;
                            lastsecond = second;
                            lastPos = pos[i];
                        }
                    }
                }
            }
            bool f = false;
            for(int i = 0; i < N; i++) {
                if(live[i]) f = true;
            }
            if(!f) break;
        }
        cout << lastsecond << ' ' << last + 1 << endl;
    }
}

C

  • dfs関数の中でbfsしたりしていますが、最初に実装した時は本当にdfsだったんです…
#include <bits/stdc++.h>
using namespace std;

#define DEBUG(x) cerr << #x << " = " << x << endl

const int MAX_N = 50;
// x, y
int field[2 * (2 * MAX_N) + 1][2 * (2 * MAX_N) + 1];

int X, Y;

typedef pair<int, int> P;
void dfs(int x, int y) {
    queue<P> Q;
    Q.push(P(x, y));
    while(!Q.empty()) {
        P p = Q.front(); Q.pop();
        for(int i = 0; i < 4; i++) {
            int dx[4] = { 1, 0, -1, 0 };
            int dy[4] = { 0, 1, 0, -1 };
            int nx = p.first + dx[i];
            int ny = p.second + dy[i];
            if(0 <= nx && nx < X && 0 <= ny && ny < Y && field[nx][ny] == 0) {
                field[nx][ny] = 1;
                Q.push(P(nx, ny));
            }
        }
    }
}

void show() {
#if 0
   cerr << '-' << endl;
   for(int i = Y - 1; i >= 0; i--) {
       for(int j = 0; j < X; j++) {
           cerr << field[j][i];
       }
       cerr << '|' << endl;
   }
   cerr << '-' << endl;
#endif
}

int main() {
    while(true) {
        int N; cin >> N;
        if(N == 0) break;
        vector<int> x1(N), y1(N), x2(N), y2(N);
        vector<int> xs;
        vector<int> ys;
        for(int i = 0; i < N; i++) {
            cin >> x1[i] >> y1[i] >> x2[i] >> y2[i];
            xs.push_back(x1[i]);
            xs.push_back(x2[i]);
            ys.push_back(y1[i]);
            ys.push_back(y2[i]);
        }
        sort(xs.begin(), xs.end());
        sort(ys.begin(), ys.end());
        xs.erase(unique(xs.begin(), xs.end()), xs.end());
        ys.erase(unique(ys.begin(), ys.end()), ys.end());
        for(int i = 0; i < N; i++) {
            x1[i] = find(xs.begin(), xs.end(), x1[i]) - xs.begin();
            y1[i] = find(ys.begin(), ys.end(), y1[i]) - ys.begin();
            x2[i] = find(xs.begin(), xs.end(), x2[i]) - xs.begin();
            y2[i] = find(ys.begin(), ys.end(), y2[i]) - ys.begin();
        }
        memset(field, 0, sizeof(field));
        for(int i = 0; i < N; i++) {
            for(int x = 2 * x1[i]; x <= 2 * x2[i]; x++) {
                field[x + 1][2 * y1[i] + 1] = 1;
                field[x + 1][2 * y2[i] + 1] = 1;
            }
            for(int y = 2 * y1[i]; y >= 2 * y2[i]; y--) {
                field[2 * x1[i] + 1][y + 1] = 1;
                field[2 * x2[i] + 1][y + 1] = 1;
            }
        }
        X = 2 * (int)xs.size() + 1;
        Y = 2 * (int)ys.size() + 1;
        show();
        int ans = 0;
        for(int x = 0; x < X; x++) {
            for(int y = 0; y < Y; y++) {
                if(field[x][y] == 0) {
                    ans++;
                    field[x][y] = 1;
                    dfs(x, y);
                    show();
                }
            }
        }
        cout << ans << endl;
    }
}

E

  • 最初は盤面の状態をstringで持っていたのですが、TLEしそうだったのでint64_tにエンコードしました
  • ぶっちゃけstringでも通ると思う
#include <bits/stdc++.h>
using namespace std;

#define DEBUG(x) cerr << #x << " = " << x << endl

const int swx[9][2] = {
    { 1, 8 },
    { 2, 0 },
    { 3, 1 },
    { 4, 2 },
    { 5, 3 },
    { 6, 4 },
    { 7, 5 },
    { 8, 6 },
    { 0, 7 }
};

const int swy[9][2] = {
    { 6, 3 },
    { 7, 4 },
    { 8, 5 },
    { 0, 6 },
    { 1, 7 },
    { 2, 8 },
    { 3, 0 },
    { 4, 1 },
    { 5, 2 }
};

typedef long long i64;
const int INF = (int)1e9;
typedef pair<int, i64> P;

template <class T, class U>
T lexical_cast(const U& from) {
    T to;
    stringstream ss;
    ss << from; ss >> to;
    return to;
}

// hidarikara
i64 stateChange(i64 S, int i, int j) {
    i = 8 - i;
    j = 8 - j;
    i64 powI = 1LL;
    i64 powJ = 1LL;
    for(int x = 0; x < i; x++) powI *= 10LL;
    for(int x = 0; x < j; x++) powJ *= 10LL;
    i64 mulI = (S / powI) % 10;
    i64 mulJ = (S / powJ) % 10;
    return S - (mulI * powI) + (mulJ * powI) - (mulJ * powJ) + (mulI * powJ);
}

int main() {
    while(true) {
        int costX, costY;
        cin >> costX >> costY;
        if(costX == 0 && costY == 0) break;
        i64 start;
        i64 goal;
        string str;
        str = "";
        for(int i = 0; i < 9; i++) {
            char c; cin >> c;
            str.push_back(c);
        }
        start = lexical_cast<i64>(str);
        str = "";
        for(int i = 0; i < 9; i++) {
            char c; cin >> c;
            str.push_back(c);
        }
        goal = lexical_cast<i64>(str);
        map<i64, int> d;
        priority_queue<P, vector<P>, greater<P> > Q;
        Q.push(P(0, start));
        d[start] = 0;
        while(!Q.empty()) {
            P p = Q.top();
            Q.pop();
            int costNow = p.first;
            i64 curS = p.second;
            if(curS == goal) break;
            if(d.count(curS) && costNow > d[curS]) continue;

            int zero;
            str = lexical_cast<string>(curS);
            if(curS < 100000000LL) zero = 0;
            else zero = find(begin(str), end(str), '0') - begin(str);

            i64 s;
            s = stateChange(curS, zero, swx[zero][0]);
            if(d.count(s) == 0 || d[s] > costNow + costX) {
                d[s] = costNow + costX;
                Q.push(P(d[s], s));
            }

            s = stateChange(curS, zero, swx[zero][1]);
            if(d.count(s) == 0 || d[s] > costNow + costX) {
                d[s] = costNow + costX;
                Q.push(P(d[s], s));
            }

            s = stateChange(curS, zero, swy[zero][0]);
            if(d.count(s) == 0 || d[s] > costNow + costY) {
                d[s] = costNow + costY;
                Q.push(P(d[s], s));
            }

            s = stateChange(curS, zero, swy[zero][1]);
            if(d.count(s) == 0 || d[s] > costNow + costY) {
                d[s] = costNow + costY;
                Q.push(P(d[s], s));
            }
        }
        cout << d[goal] << endl;
    }
}