2013年11月9日土曜日

パソコン甲子園(PCK)2013 もう一つの本戦 参加記

予選に落ちた後悔を引きずりながら先輩と参加。

4AC+0WAでした。
予選は6AC+4WA。僕の緊張が極限に達して自滅しました。

1→5→2→3の順でAC。3のAC時刻が17:20:09とかなっていたので更新されないじゃんとなって萎えました。
ちょっと本番と変えてるけど、ソース。

テンプレート


用意してなかったので先輩のテンプレートをコピペしました。若干省略。
#include<iostream>
#include<string>
#include<bitset>
#include<cctype>
#include<cstdlib>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<sstream>
#include<iterator>
#include<algorithm>
#include<complex>
using namespace std;
 
// structure
typedef long long ll;
typedef pair < int , int > Pi;
typedef pair < int , Pi > Pii;
 
#define INF (1 << 28)
#define SQR(x) ((x)*(x))
 
//repetition
#define reps(i,j,n) for(int i = j ; i < n ; ++i)
#define rep(i, n) reps(i,0,n)
#define EACH(i,c) for(__typeof((c).begin()) ;i=(c).begin(); i!=(c).end(); ++i)
 
// containar
#define ALL(v) (v).begin(), (v).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define sz(z) (int)((z).size())
#define mp(a,b) make_pair(a,b)
#define pb(a) push_back(a)
#define UNQ(s) {sort(ALL(s));(s).erase(unique(ALL(s)),(s).end());}
#define fr first
#define sc second

// PROG START

int main(){

}

問題1.テニス(6点)


パッと見た感じ再帰しか浮かばなかったので再帰で解きました。 答えはvectorで持たせました。
int A,B;
vector<string> ans;
void solve(int a,int b,string t){
  if(a == A && b == B){
    ans.pb(t);
    return;
  }
  if(a > 6 || b > 6) return;
  if(a == 5 && b == 5) return;
  if((a == 5 && b < 4) || (a < 4 && b == 5)) return;
  if((a == 6 && b == 4) || (a == 4 && b== 6)) return;
  solve(a+1,b,t+"A");
  solve(a,b+1,t+"B");
}
int main(){
  cin >> A >> B;
  solve(0,0,"");
  sort(ALL(ans));
  rep(i,ans.size()) cout << ans[i] << endl;
}


問題2.親方の給料計算(6点)


超難問。O(N*M*L) = O(10^10) で逝くじゃんと思って怖くて触れにくかった問題です。
TLE覚悟でソースを出してみたらACして,ファ??ってなりました。
正答率10%切ってて,下のソースを早くしようとしたけど,ちょっと察せなかった。
int main(){
  int N, M, a, b, c, L;
  cin >> N >> M;
  vector<Pi> vc[N];
  int cost[M];
  while(cin >> a >> b >> c , a + b + c){
    vc[a-1].push_back(Pi(b-1,c));
  }
  cin >> L;
  while(L--){
    rep(i,M) cin >> cost[i];
    rep(i,N){
      int sum = 0;
      rep(j,vc[i].size())
        sum += cost[vc[i][j].fr] * vc[i][j].sc;
      cout << (i ? " " : "") << sum;
    }
    cout << endl;
  }
}


問題3.塵劫記(6点)


みんなACしてて「コレ簡単?(困惑)」になっていた。多倍長乗算。
変換する部分は事前に先輩が実装してくれた。凄い。
あとは多倍長,書きたくなくて書かなかったが、仕方なくやったらすぐ実装できて良かった。
string lis[] = {
  "","Man","Oku","Cho","Kei","Gai","Jo","Jou","Ko","Kan",
  "Sei","Sai","Gok","Ggs","Asg","Nyt","Fks","Mts",
};
string KAKEZAN(string a,string b){
  int ans[100] = {};
  string rec;
  reverse(ALL(a));
  reverse(ALL(b));
  rep(i,a.size()) rep(j,b.size()){
    ans[i+j] += (a[i] - '0') * (b[j] - '0');
  }
  rep(i,99){
    ans[i+1] += ans[i] / 10;
    rec += (ans[i] % 10) + '0';
  }
  reverse(ALL(rec));
  int cnt = 0;
  while(rec[cnt] == '0') cnt++;
  return rec.substr(cnt);
}
void ZIN(string s){
  vector<string> v;
  string ret;
  reverse(ALL(s));
  for(int i = 0 ; i < (int)s.size() ; i += 4){
    string cut = s.substr(i,min(4,sz(s)-i));
    string Class = lis[i/4];
    reverse(ALL(cut));
    int pos = -1;
    rep(j,cut.size()){
      if(cut[j] != '0'){ pos = j; break; };
    }
    if(pos == -1) continue;
    string in;
    reps(j,pos,cut.size()) in += cut[j];
    v.pb(in+Class);
  }
  reverse(ALL(v));
  rep(i,v.size()) cout << v[i];
  cout << endl;
}
int main(){
  string a;
  int b;
  while(cin >> a >> b , a != "0" || b != 0){
    string ret = "1";
    rep(i,b) ret = KAKEZAN(ret,a);
    ZIN(ret);
  }
}

問題5.無限急行(8点)


先輩が他の問題を解読しているうちに僕が実装。
一発ACするとは思っていなかった。
たくさん関数分けて,たくさんビットシフトすればいいんじゃね的な考え方で
バグってもいいので適当に書いた。十分このソースも汚いけど、本番はそれ以上に汚かった。
int s, d;
bool check(int train,int n){
  if(!train) return true;
  int shift = pow(2,train);
  if(n + shift > d) return false;
  rep(i,32){
    if(abs(n) & (1<<i)){
      if(i && (1<<i) % shift == 0) return true;
      else return false;
    }
  }
  return true;
}
int cnt(int no){
  int i = 0;
  while(check(i,no)) i++;
  return i - 1;
}
int solve(int now, int cost){
  if(now == d) return cost;
  int train = cnt(now);
  if(now + pow(2,train) <= d){
    return solve(now+pow(2,train),cost+1);
  }else{
    return solve(now,cost+1);
  }
}
int main(){
  int N;
  cin >> N;
  while(N--){
    cin >> s >> d;
    cout << solve(s,0) << endl;
  }
}
5問目と3問目解けた高揚感で4問目サボってしまったのが反省点。 ソートして再帰すればHappyそうなので今度やって挙げます。

11/12追記
、と思ったけど先輩が解いてくれてたのでやめました。
http://hayashiya.hatenablog.com/entry/2013/11/12/205702
11/14追記
2位だったので図書カード獲得した。

0 件のコメント:

コメントを投稿