ichirin2501's diary

いっちりーん。

Google Code Jam 2010 :: Qualification Round

参加者の皆さん、お疲れ様でした。
結果は、
AとCを完答して、Score66でした。
B問題は最後まで意味が分からず…。
感想としては、
GCJ is very difficult english game.

A__Snapper Chain

ただの2進数の問題。10進数のKが与えられて、下位N桁全てのビットが1ならON、違うならOFF

#include <iostream>
using namespace std;
int main()
{
  int N,K,T;
  cin>>T;
  for(int x=1; x<=T; x++){
    cin>>N>>K;
    printf("Case #%d: %s\n",x,( (K&((1<<N)-1))==((1<<N)-1)? "ON" : "OFF"));
  }
  return 0;
}

C__Theme Park

1日にR回運用するK人乗りのロケットコースターがあって、1人あたり1ユーロの儲けがある。
グループ数Nの客のデータが1行で与えられて、
1 4 2 1
のとき、1人のグループ、4人のグループ、2人のグループ、1人のグループ、の行列で、先頭から順番に乗る。
グループは必ず全員一緒に乗らないといけない。Kが6のとき、
1人のグループと、4人のグループが乗れるが、2人のグループは乗れない。
よって、[ 1 4 ]の計5人(5ユーロ)が1回目に乗ることになる。乗った後は、行列の後ろに並ぶ。
このときの客データは
2 1 1 4
これをR回繰り返したときの最大ユーロを求める。


smallだけなら、てきとーにループを廻すだけでも十分間に合う。
ただ、largeの場合は少し工夫が必要。
何回かロケットコースターを運用すると、客の行列データがループに入る。
行列データの状態とその状態に対する儲けのユーロを記録しておき、
ループに入ったら残りの運用回数とループの周期から、儲けユーロを計算する。

#include <iostream>
#include <map>
#include <set>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
  int T;
  cin>>T;
  for(int round=1; round<=T; round++){
    int R,k,N;
    long long ans = 0;
    vector<int> v;
    vector< pair<vector<int>,long long> > vv;
    set<vector<int> > set_vec;
    
    cin>>R>>k>>N;
    for(int i=0; i<N; i++){ int a; cin>>a; v.push_back(a); }
    
    for(int r=0; r<R; r++){
      vector<int> hikae = v;
      long long sum = 0;
      int j;
      
      for(j=0; j<N; j++){
        if( sum+v[j]>k )break;
        sum += v[j];
        v.push_back( v[j] );
      }
      v.erase( v.begin(), v.begin()+j );      

      if( set_vec.find( hikae ) != set_vec.end() ){
        int i,shuuki,amari,cnt;
        for(i=0; i<vv.size(); i++)if( vv[i].first==hikae )break;
        shuuki = vv.size() - i;
        cnt = R-r;
        amari  = cnt % shuuki;
        for(; i<vv.size() && cnt>0 ; i++){
          ans += ( vv[i].second * ( (R-r)/shuuki + ( amari>0 ? 1: 0 ) ) );
          if( amari>0 )amari--;
          cnt--;
        }
        break;
      }else{
        set_vec.insert( hikae );
        vv.push_back( make_pair(hikae,sum) );
        ans += sum;
      }
    }
    printf("Case #%d: %lld\n",round,ans);
  }
  
  return 0;
}


5/10 追記:
Cコードの明らかにデバッグ用、無意味な処理部分を削除。