JMK quo vadis?

SRM451 연습

일루옹이 타겟이 된 전설의 매치. 과거로 쭉 거슬러 올라가면서 연습하기로 맘먹고 돌아보았다. 간단한 250, 꽤나 복잡한 DP 500, 그리고 안드로메다 1000 의 구성. 1000 은 이렇게 저렇게 짜 봤는데 잘 안나온다. -_ - 모든 valid 한 비트마스크의 수가 피보나치 수열이라는 점을 이용하면 O(fib(w)wh) 에 동적 계획법을 할 수 있다는 요지인데.. 구현 디테일을 잘 모르겠음. ;;; 250 500 둘다 헤맸고, 500 에서는 이분검색에서 boundary 값 잘못 지정하는 거랑 함수 입력 정의 boundary 값 헷갈려서 틀림.

250 MagicalSource

시뮬레이션하려고 한참 폼잡고 있다가 그냥 풀은.. OTL

lang:cpp
struct MagicalSource {
    long long calculate( long long x ) {
        long long t = 1;
        while(t*10+1 <= x) t = t*10+1;
        while(x%t) t /= 10;
        return x/t;
    }
};

500 BaronsAndCoins

캡 복잡하게 짰다. -.-;; O(nn10000) 과 O(n*n) 의 두 가지 어프로치가 있는 것 같은데, 나는 후자로 짰음.

lang:cpp
const int INF = 987654321;
struct BaronsAndCoins {
    vector<pair<int,int> > coin;
    int cache[100][100];
    int sigma(int a, int b)
    {
        return b*(b+1)/2 - a*(a-1)/2;
    }
    int go(int last, int taken)
    {
        int& ret = cache[last][taken];
        if(ret != -1) return ret;
        ret = INF;
        if(taken == 1) return ret; // oops
        int track = -1;
        REP(before,last)
        {
            int ydiff = coin[last].first - coin[before].first;
            int xdiff = coin[last].second - coin[before].second;
            int minMoveSize = go(before, taken-1);
            if(minMoveSize == INF) continue;
            ++minMoveSize;
//            if(ydiff > 0 && xdiff >= minMove(minMoveSize, ydiff))
            if(ydiff > 0 && xdiff >= sigma(minMoveSize, minMoveSize + ydiff - 1))
            {
                // it's impossible to end at lo, possible to end at hi
                int lo = 0;
                int hi = xdiff;
                while(lo+1 < hi)
                {
                    int mid = (lo + hi) / 2;
                    if(xdiff <= sigma(mid - ydiff + 1, mid))
                        hi = mid;
                    else
                        lo = mid;
                }
                if(ret > hi) track = before;
                ret = min(ret, hi);
            }
        }
        //if(ret != INF)
        //printf("arrive at %d, catching %d => min move is %d from %d\n", last, taken, ret, track);

        return ret;
    }
    int getMaximum( vector <int> x, vector <int> y ) {
        CLEAR(cache,-1);
        coin.pb(make_pair(0, 0));
        REP(i,x.sz) coin.pb(make_pair(y[i], x[i]));
        cache[0][1] = 0;
        sort(all(coin));
        for(int amt = coin.sz; amt >= 1; --amt)
            REP(end,coin.sz) 
                if(go(end, amt) < INF) 
                    return amt-1;
        // oops
        return -1;
    }
};

1000 BrickPuzzle

모든 블럭이 두줄이라던가 이런 트리비얼한 것은 쉬운데.. 구현에서 약한 건가 ;ㅁ;

2009-10-25 15:09:04 | JM | /logs/topcoder/ | 3 개의 댓글들
wook
2009-10-25 15:22:16
저도 이거돌 때 미뎜에서 특정 칸에서 특정 칸으로 갈 수 있는지 체크하는거에서 무지 삽질했는데 나중에 사람들 한거 보니까 무지 간단한 방법이 있더군요 orz
ltdtl
2009-10-25 22:47:48
훼인들..
JM
2009-10-27 22:05:32
wook/ 다른 생각 하기 귀찮았던 1인.. 근데 진짜 있네. ㅋㅋ
ltdtl/ 흥이다

댓글 남기기