Isa@Diary

ソフトウェア開発やってます。プログラミングとか、US生活とかについて書きます。

Google Code Jam Round.1C

結果

A(small/large) C(small)
565th 40pts 1:36:15

なんとか通過したよー。
Round2通過は無理だろうけど精一杯がんばります。

A Diamond Inheritance

全ての点からDFSして既にvisitedの点に当たったらYes、そうでなければNo。

C Box Factory

ぱっと見でLCSっぽいDPだろうなぁと思う。
問題分から、同じ種類のbox/toyが連続してこないという確信が得られなかったので
まず連続する同じ種類の生産をまとめるようにする。

まず

dp[i][j] := i-thBox,j-thToyまで使ったときの発送できる最大値

として考えてみる。

  • >種類が同じなら詰めるだけ詰めて余ったのは捨てる、種類が違ったらbox/toyのどちらかを全て捨てる
  • >Pretest1あった!
  • >small提出
  • >WA
  • >Pretest2が合ってない←アホ
  • >詰めたあと捨てないほうがいい場合もあるのか…
  • >dp[i][j][k][l]でk,l=個数とすると明らかにMLE
  • >solve(i,j,k,l)で再帰にしてみよう
  • >サンプル合う
  • >small,correct
  • >largeのランダムジェネレータを書く
  • >やっぱりTLE
  • >k,lはあんまりいろんな値を取らない気がするのでメモ化してみる
  • >N=100,M=100でもすぐ返ってくるようになる
  • >submit

結果的にWAだった、原因は1ケースごとにメモの値を消していなかったこと。
複数ケースの場合は特に注意したい…。

以下ソース

#define dump(x)  cerr << #x << " = " << (x) << endl;
#define PB push_back
#define MP make_pair
#define ll long long

inline int toInt(string s){int v;istringstream sin(s);sin>>v;return v;}
template<class T> inline string toString(T x){ostringstream sout;sout<<x;return sout.str();}

class State{
public:
    int bi,ti;
    ll bn,tn;
    State(int _bi, int _ti, ll _bn, ll _tn){
        bi = _bi;
        ti = _ti;
        bn = _bn;
        tn = _tn;
    }
    
    bool operator <(State arg) const{
        if(bi != arg.bi){
            return bi < arg.bi;
        }
        if(ti != arg.ti){
            return ti < arg.ti;
        }
        if(bn != arg.bn){
            return bn < arg.bn;
        }
        return tn < arg.tn;
    }
};

map<State, ll> ma;
int n,m;
vector<ll> box, toy;
vector<int> kbox, ktoy;

ll solve(int bi, int ti, ll bn, ll tn){
    ll ret=0,tmp;
    if(bi >= n || ti >= m) return 0;
    if(ma.find(State(bi,ti,bn,tn)) != ma.end()){
        return ma[State(bi,ti,bn,tn)];
    }

    if(kbox[bi] == ktoy[ti]){
        //すぐ捨てる
        ret = max(ret, solve(bi+1, ti+1, box[bi+1], toy[ti+1]) + min(bn,tn));
        //とっておく
        if(bn > tn){
            ret = max(ret, solve(bi, ti+1, bn-tn, toy[ti+1]) + min(bn,tn));
        }else if(bn < tn){
            ret = max(ret, solve(bi+1, ti, box[bi+1], tn-bn) + min(bn,tn));
        }
    }else{
        ret = max(ret, solve(bi+1,ti,box[bi+1], tn));
        ret = max(ret, solve(bi,ti+1,bn, toy[ti+1]));
    }
    return ma[State(bi,ti,bn,tn)] = ret;
}

int main(){
    int t;
    cin >> t;
    for(int x=1;x<=t;x++){

        cin >> n >> m;
        ll numtmp=0,ktmp;
        ll kind, num;
        box.clear();
        toy.clear();
        kbox.clear();
        ktoy.clear();
        ma.clear();
        cin >> num >> kind;
        for(int i=1;i<n;i++){
            cin >> numtmp >> ktmp;
            if(ktmp == kind){
                num += numtmp;
            }else{
                box.PB(num);
                kbox.PB(kind);
                num = numtmp;
                kind = ktmp;
            }
        }
        box.PB(num);
        kbox.PB(kind);

        cin >> num >> kind;
        for(int i=1;i<m;i++){
            cin >> numtmp >> ktmp;
            if(ktmp == kind){
                num += numtmp;
            }else{
                toy.PB(num);
                ktoy.PB(kind);
                num = numtmp;
                kind = ktmp;
            }
        }
        toy.PB(num);
        ktoy.PB(kind);

        n = box.size();
        m = toy.size();
        ll ret;
        ret = solve(0,0,box[0],toy[0]);
        printf("Case #%d: %lld\n",x,ret);
    }
}