TCO14 Round2A

この記事を書いてる時に1Bの記事が事故死してしまった…。まぁいいか。

  • -

250. SixteenBricks

問題:1*1*h[i]の角柱を4×4のグリッドに並べた時の最大表面積を求める問題。

  • greedyかなぁと思ったけどsample2が倒せなかった。
  • 安全にbitDPとか出来ないかなと思ったけど、思いつかず。
  • Challengeで人のコードを見たら、そりゃそうか、という感じだった。
  • 以下は、本番後にbitDPしてみたコード。この解法好きです。
class SixteenBricks {
private:
    int bitCount(int t){
        int res = 0;
        for(int i=t;i;i&=i-1) res++;
        return res;
    }
    int additionalScore(int mask, int pos, int h){
        int res = 0;
        int x = pos/4, y = pos%4;
        if(x > 0 && (mask&(1<<(pos-4)))) res -= h;
        else                             res += h;
        if(x < 3 && (mask&(1<<(pos+4)))) res -= h;
        else                             res += h;
        if(y > 0 && (mask&(1<<(pos-1)))) res -= h;
        else                             res += h;
        if(y < 3 && (mask&(1<<(pos+1)))) res -= h;
        else                             res += h;
        return res;
    }
public:
    int maximumSurface(vector <int> height){
        static int dp[1<<16];
        memset(dp, 0, sizeof(dp));
        dp[0] = 16;
        sort(height.rbegin(), height.rend());
        for(int i=0;i<(1<<16)-1;i++){
            int idx = bitCount(i);
            for(int j=0;j<16;j++){
                if(i&(1<<j)) continue;
                dp[i|(1<<j)] = max(dp[i|(1<<j)], dp[i]+additionalScore(i, j, height[idx]));
            }
        }
        return dp[(1<<16)-1];
    }
};

500. NarrowPassage

問題:長さLの細い道で、n匹の狼が目的地に向かう。すれ違うにはx=0かx=Lの地点までいかないといけない。狼の移動距離の合計の最小値は?

  • x=0ですれ違うグループ、x=Lですれ違うグループの作り方を全探索すれば…と思った
  • それで通る問題が500で出るわけが無い…と思って手元で撃墜ケースを探す
  • x=0ですれ違い→x=Lですれ違い のパターンが最適な事もありそう
  • というわけで、2回出たり入ったりするのを全探索してみた。
  • sample3にやられる
  • なん…だと…。
  • バグかと思ってコードを見てたけどバグは見つからず。
  • 計算量に余裕があったので、3回出たり入ったりしてみた。
  • sample3が倒せてしまった。
  • 良く分からんけど250が解けてなかったので投げた。
  • 通ったのはsample3のおかげと言わざるを得ません。
  • 以下は本番で書いたコード。酷いコピペ実装だったし、よく通ったなと思う。
class NarrowPassage {
public:
    int minDist(int L, vector <int> a, vector <int> b) {
        int n = a.size();
        vector< pair<int,int> > vp;
        vector< pair<int,int> > p1(n), p2(n), p3(n);
        for(int i=0;i<n;i++) vp.push_back(make_pair(a[i],b[i]));
        sort(vp.begin(), vp.end());
        int res = 1000000007;
        for(int i=0;i<=n;i++){
            for(int k=0;k<n;k++) p1[k] = vp[k];
            int tmp1 = 0;
            for(int k=0;k<i;k++){
                tmp1 += p1[k].first;
                p1[k].first = 0;
            }
            sort(p1.begin(), p1.end());
            for(int j=0;j<=n;j++){
                int tmp2 = tmp1;
                for(int k=0;k<n;k++) p2[k] = p1[k];
                for(int k=0;k<j;k++){
                    tmp2 += L - p2[n-1-k].first;
                    p2[n-1-k].first = L;
                }
                sort(p2.begin(), p2.end());
                for(int l=0;l<=n;l++){
                    for(int k=0;k<n;k++) p3[k] = p2[k];
                    int tmp3 = tmp2;
                    for(int k=0;k<l;k++){
                        tmp3 += p3[k].first;
                        p3[k].first = 0;
                    }
                    sort(p3.begin(), p3.end());
                    bool ok = true;
                    for(int k=0;k+1<n;k++){
                        if(p3[k].second > p3[k+1].second) ok = false;
                    }
                    if(!ok) continue;
                    for(int k=0;k<n;k++){
                        tmp3 += abs(p3[k].first - p3[k].second);
                    }
                    res = min(tmp3, res);
                }
            }
        }
        for(int i=0;i<=n;i++){
            for(int k=0;k<n;k++) p1[k] = vp[k];
            int tmp1 = 0;
            for(int k=0;k<i;k++){
                tmp1 += L - p1[n-1-k].first;
                p1[n-1-k].first = L;
            }
            sort(p1.begin(), p1.end());
            for(int j=0;j<=n;j++){
                int tmp2 = tmp1;
                for(int k=0;k<n;k++) p2[k] = p1[k];
                for(int k=0;k<j;k++){
                    tmp2 += p2[k].first;
                    p2[k].first = 0;
                }
                sort(p2.begin(), p2.end());
                for(int l=0;l<=n;l++){
                    for(int k=0;k<n;k++) p3[k] = p2[k];
                    int tmp3 = tmp2;
                    for(int k=0;k<l;k++){
                        tmp3 += L - p3[n-1-k].first;
                        p3[n-1-k].first = L;
                    }
                    sort(p3.begin(), p3.end());
                    bool ok = true;
                    for(int k=0;k+1<n;k++){
                        if(p3[k].second > p3[k+1].second) ok = false;
                    }
                    if(!ok) continue;
                    for(int k=0;k<n;k++){
                        tmp3 += abs(p3[k].first - p3[k].second);
                    }
                    res = min(tmp3, res);
                }
            }
        }
        return res;
    }
};

1000. TreePuzzle

  • 見てない。
  • -

結果:-- / AC / -- ,+0, 255.25pt, 101位
レーティング:2404 -> 2442

運が良かったとしか言いようのない結果です。250でbitDP思いつけなかったのが反省点。