2009-09-04
Google Code Jam: Qualification Round (24hrs)
GCJ2009 | |
![]()
Google Code Jam初参加の巻
http://code.google.com/codejam/contest
- 参加
- 結果
問題と入力データはPrevious Contestsで見られます。
基本方針
(A) AlienLanguage.cpp
- 正規表現ですね
- ここは自力でパースできるもんねってところを見せておく(=バグの温床を増やす)か
- 26bitだしintでマスク作るか
- 最大最悪ケースのテストデータとかAWKで作ってテストしてから投稿
- てか別にAWKで解いて終わりで良かったのでは
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int L, D, N;
int parse(vector<int>& ans, const string& s)
{
ans.resize(L); for(int i=0;i<L;i++) ans[i]=0;
int p=0;
for(int i=0,len=s.size(); i<len;){
int c=s[i++];
if (c=='(') {
while((c=s[i++])!=')'){
ans[p] |= 1 << (c-'a');
}
p++;
} else {
ans[p++] = 1 << (c-'a');
}
}
return p;
}
main()
{
cin >> L >> D >> N;
// L: [1-10] or [1-15]
// D: [1-25] or [1-5000]
// N: [1-10] or [1-500]
// loading lexicon
vector<vector<int> > lexicon(D,vector<int>(L,0));
for(int d=0;d<D;d++){
string s; cin >> s;
int p = parse(lexicon[d], s);
}
// loading cases
for(int n=0;n<N;n++){
string s; cin >> s;
vector<int> case_(L,0);
int p = parse(case_, s);
int K = 0;
for(int d=0;d<D;d++){
int x=0;
for(int i=0;i<L;i++) if (lexicon[d][i] & case_[i]) x++;
if (x==L) K++;
}
printf("Case #%d: %d\n", 1+n, K);
}
}
(B) Watershed.cpp
TopCoderだとこの程度のでも焦ってミスるんだよね
- 各地点から東西南北どちらに水が流れるか、あるいは流れない(sink)かを調べる。sentinelぐらい使えるもんね
- 調べたついでに、流れ先の「流れ元リスト」に自分を登録
- sinkが現れたら仮idをふっておく
- 全sinkについて、流れ元リストを頼りに再帰的に全地点の流れ先sink(仮id)を求め伝播させる
- 出力時に、sink仮idを出現順にa-zに置き換え表示
- 最大最悪ケースのテストデータとか(AWKで)作ってテストしてから投稿
- これもAWKで解けるレベル
- 最悪すぎてsink数が(問題制約の)26を超えすぎて出力が変な文字で埋まったとか内緒
#include <iostream>
#include <vector>
#include <string>
#include <list>
using namespace std;
#define sz(a) int((a).size())
#define pb push_back
#define all(c) (c).begin(),(c).end()
#define tr(c,i) for(typeof((c).begin()) i=(c).begin(); i!=(c).end(); i++)
#define rep(var,n) for(int var=0;var<(n);var++)
vector<vector<int> > m; // source map
vector<vector<int> > d; // N=0 W=1 E=2 S=3 // sink=-1
vector<pair<int,int> > sink;
vector<vector<vector< pair<int,int> > > > chain;
vector<vector<int> > sm;
void paint(int h, int w, int sid)
{
tr(chain[h][w],it) {
int h2=it->first, w2=it->second;
sm[h2][w2] = sid;
paint(h2,w2,sid);
}
}
main()
{
int T, H, W, sid;
cin >> T;
rep(t,T){
printf("Case #%d:\n", 1+t);
sid = 0;
cin >> H >> W;
m.resize(H+2);
sm.resize(H+2);
d.resize(H+2);
chain.resize(H+2);
sink.resize(0);
rep(h,H+2){
m[h].resize(W+2);
sm[h].resize(W+2);
d[h].resize(W+2);
chain[h].resize(W+2);
rep(w,W+2) {
m[h][w] = 99999;
sm[h][w] = 99999;
d[h][w] = -1;
chain[h][w].resize(0);
}
}
for(int h=1;h<=H;h++){
for(int w=1;w<=W;w++){
cin >> m[h][w];
}
}
for(int h=1;h<=H;h++){
for(int w=1;w<=W;w++){
int a=m[h][w], dir=-1;
if (m[h-1][w]<a) { dir=0; a=m[h-1][w]; }
if (m[h][w-1]<a) { dir=1; a=m[h][w-1]; }
if (m[h][w+1]<a) { dir=2; a=m[h][w+1]; }
if (m[h+1][w]<a) { dir=3; a=m[h+1][w]; }
d[h][w] = dir;
switch(dir){
case -1: sink.push_back( make_pair(h,w) ); sm[h][w] = sid++; break;
case 0: chain[h-1][w].push_back( make_pair(h,w) ); break;
case 1: chain[h][w-1].push_back( make_pair(h,w) ); break;
case 2: chain[h][w+1].push_back( make_pair(h,w) ); break;
case 3: chain[h+1][w].push_back( make_pair(h,w) ); break;
}
}
}
rep(s,sid){
int h=sink[s].first, w=sink[s].second;
paint(h,w,s);
}
// allocate characters [a-z]
vector<int> corr(sid,0); int ch='a';
for(int h=1;h<=H;h++){
for(int w=1;w<=W;w++){
int id=sm[h][w];
if (corr[id]) continue;
corr[id]=ch++;
}
}
// replace & output
rep(h,H){
string o; o.resize(W*2-1);
rep(i,W*2-1) o[i]=' ';
rep(w,W){
o[w*2] = corr[sm[h+1][w+1]];
}
cout << o << endl;
}
}
}
(C) WelcomeToCodeJam.cpp
- 教科書にDPの例として載りそうなくらいDP。
- 最初 gets() 使って書いてたけど、コンパイルするとwarningが出るのが嫌なので fgets() に書き換えた。別にwarning出るくらいいいのに… で、fgets()だと改行コードも入るので501では足りない・・・ (pts-=23)
- 面倒くさがって、500字のテストを書かなかったのも良くない
※以下、投稿時のコード
#include <iostream>
#include <vector>
#include <string>
#include <map>
using namespace std;
#define sz(a) int((a).size())
#define pb push_back
#define all(c) (c).begin(),(c).end()
#define tr(c,i) for(typeof((c).begin()) i=(c).begin(); i!=(c).end(); i++)
#define rep(var,n) for(int var=0;var<(n);var++)
#define found(s,e) ((s).find(e)!=(s).end())
char msg[502], *salut="welcome to code jam";
int msg_len, salut_len=19;
map<pair<int,int>,long long> ht;
long long find_welcome(int msg_ix, int salut_ix)
{
if (msg_len - msg_ix < salut_len - salut_ix) return 0LL;
pair<int,int> key = make_pair(msg_ix,salut_ix);
if (found(ht,key)) return ht[key];
long long cnt = 0LL;
if (msg[msg_ix] == salut[salut_ix]) {
if (salut_ix == salut_len-1)
cnt++;
else
cnt += find_welcome(msg_ix+1, salut_ix+1);
}
cnt += find_welcome(msg_ix+1, salut_ix);
cnt %= 10000LL;
ht[key] = cnt;
return cnt;
}
main()
{
int N;
cin >> N;
fgets(msg,501,stdin); // gets(msg);
rep(n,N){
ht.clear();
// gets(msg);
// msg_len=strlen(msg);
fgets(msg,501,stdin); ←501を502にすれば通る
rep(i,strlen(msg)) if(msg[i]<0x20){ msg_len=i; msg[i]=0; break; }
long long cnt = find_welcome(0,0);
printf("Case #%d: %04lld\n", 1+n, cnt);
}
}
追記: getline()
それ
string s; getline(cin, s);
でできるよ(泣)
コメント
トラックバック - https://topcoder-g-hatena-ne-jp.jag-icpc.org/n4_t/20090904