2009-09-13
Google Code Jam: Round 1C (2.5hrs)
A: All Your Base
- 21分
- 後で通してみる→通らない
- 111111... みたいな時に1進法になってたので直す→通った
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <set>
#include <map>
#include <list>
#include <queue>
#include <algorithm>
#include <cmath>
//#include "cout.h"
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())
main()
{
int T; cin >> T;
string s;
rep(t,T){
cin >> s;
int len=sz(s);
map<int,int> chars;
rep(i,len) chars[s[i]] = -1;
// int base_min = sz(chars); /// ##OOPS##
int base_min = max(sz(chars),2);
vector<int> trans(len,-1);
chars[s[0]] = 1;
int n=0;
long long result = 0LL;
rep(i,len) {
if (chars[s[i]] < 0) {
chars[s[i]] = n++; if (n==1) n=2;
}
trans[i] = chars[s[i]];
result = result * base_min + trans[i];
}
printf("Case #%d: %lld\n", 1+t, result);
}
}
B: Center of Mass
- 27分
- 後で通してみる→通らない
- 合成した速度が 0 のときに divided by zero
- あと、方程式の誤差でNaNが出てたので式を変更→これで通った
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <set>
#include <map>
#include <list>
#include <queue>
#include <algorithm>
#include <cmath>
//#include "cout.h"
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())
main()
{
int T; cin >> T; // 1..100
rep(t,T){
int N; cin >> N; // 3..10(or 500)
double x=0,y=0,z=0,vx=0,vy=0,vz=0;
rep(n,N){
int x_,y_,z_,vx_,vy_,vz_;
cin >> x_ >> y_ >> z_ >> vx_ >> vy_ >> vz_;
x += x_; y += y_; z += z_;
vx += vx_; vy += vy_; vz += vz_;
}
x /= N; y /= N; z /= N;
vx /= N; vy /= N; vz /= N;
// (x + vx*t, y + vy*t, z + vz*t)
// x2 + y2 + z2
// (2 x vx + 2 y vy + 2 z vz) t
// (vx2 + vy2 + vz2) t2
// (x,y,z) + (vx,vy,vz)t = (x + vx.t, y + vy.t, z + vz.t)
// distance = sqrt{ (x^2 + y^2 + z^2) + 2t(x.vx + y.vy + z.vz) + t^2(vx^2 + vy^2 + vz^2) }
double c = x*x + y*y + z*z;
double b = x*vx + y*vy + z*vz;
double a = vx*vx + vy*vy + vz*vz;
double tmin, dmin;
if (a == 0) { //### a=0の分岐を追加
// v = 0
tmin = 0;
dmin = sqrt(c);
} else {
// a t2 + 2 b t + c
// 2(at + b) = 0, t = -b/a
double t = -b/a;
tmin = max(t, 0.0);
//dmin = sqrt(tmin*tmin*a + tmin*b*2 + c); //###時々0をわずかながら下回りNaNになるので、下の式に変更
dmin = sqrt( (x + vx*tmin) * (x + vx*tmin)
+ (y + vy*tmin) * (y + vy*tmin)
+ (z + vz*tmin) * (z + vz*tmin) );
}
printf("Case #%d: %10.8f %10.8f¥n", 1+t, dmin, tmin);
}
}
C: Bribe the Prisoners
- 見てない
- とりあえず上の2問で50点。wrong answerを2回かましてペナルティ食らったと思うけど500番台で通過できるスコア(C解いてたらもうちょっと上か)
- あとで見る。(これが1時間ちょいで解ければフルスコア通過)
- 見てみた (2009/9/20)
- これが一番簡単な気がした。毎回分断されていくので単純なDP。配点50って何
- 29分
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <set>
#include <map>
#include <list>
#include <queue>
#include <algorithm>
#include <cmath>
//#include "cout.h"
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())
int P, Q;
vector<int> qs;
map<pair<int,int>,int> m;
int sub(int left, int right)
{
pair<int,int> k = make_pair(left,right);
if (found(m,k)) {
//printf("sub(%d, %d) == %d¥n", left, right, m[k]);
return m[k];
}
int retmin = INT_MAX;
tr(qs,it){
if (*it < left || right < *it) continue;
int ret = right - left; // 1-20なら19
if (left < *it) ret += sub(left, *it - 1);
if (*it < right) ret += sub(*it + 1, right);
if (ret < retmin) retmin = ret;
}
if (retmin == INT_MAX) retmin = 0;
m[k] = retmin;
//printf("sub(%d, %d) := %d¥n", left, right, m[k]);
return retmin;
}
main()
{
int T; cin >> T; // 1..100
rep(t,T){
cin >> P >> Q;
qs.resize(Q); rep(q,Q) cin >> qs[q];
sort(all(qs));
m.clear();
printf("Case #%d: %d¥n", 1+t, sub(1,P));
}
}
Google Code Jam: Round 1B (2.5hrs)
- 9/13 1:00am (JST)〜
- 1Aで落ちてたらいけないので、一応1amに待機していた
- 参加できない (watch only)
- でも問題は見れるので解くよ
- A と B まで解いて1時間弱
A: Decision Treee
もちろんschemeで解きました
- printfは自作のやつを使ってます。(ソース略)
;;;
;;; in Gauche 0.8.14
;;; http://practical-scheme.net/gauche/
;;;
(use srfi-1)
(define (read-int)
(x->integer (read-line)))
(define (read-args-in-line)
(let1 s (string-append "(" (read-line) ")")
(read-from-string s)))
(define (read-sexp-in-lines l)
(let loop ((i 0) (s ""))
(if (= i l) (read-from-string s)
(loop (+ i 1) (string-append s (read-line))))))
(define (tree-weight tr) (car tr)) ; [0.0 .. 1.0]
(define (tree-has-child? tr) (not (null? (cdr tr))))
(define (tree-feature tr) (if (tree-has-child? tr) (cadr tr) #f))
(define (tree-tree1 tr) (if (tree-has-child? tr) (caddr tr) #f))
(define (tree-tree2 tr) (if (tree-has-child? tr) (cadddr tr) #f))
(define (dive tr fht p)
(let1 p* (* p (tree-weight tr))
(if (tree-has-child? tr)
(if (hash-table-get fht (tree-feature tr) #f)
(dive (tree-tree1 tr) fht p*)
(dive (tree-tree2 tr) fht p*))
p*)))
(let1 N (read-int)
(dotimes (testcase N)
(format #t "Case #~d:¥n" (+ 1 testcase))
(let* ([L (read-int)]
[tr (read-sexp-in-lines L)]
[number-of-animals (read-int)])
(dotimes (i number-of-animals)
(let* ([animal-n-features (read-args-in-line)]
[animal (car animal-n-features)]
[features (cddr animal-n-features)]
[fht (make-hash-table 'eq?)])
(for-each (cut hash-table-put! fht <> #t) features)
(let1 c (dive tr fht 1.0)
(printf "%9.7f¥n" c)
))))))
B: The Next Number
- next_permutation使いたいのでC++
- 一周回って戻ってきてたら繰り上がり、0を1つ挿入
- 最初が0の場合は0でない最初の数字を最初に持ってくる操作が必要。最初これをnext_permutationのループで書いてたが最悪ケースで全然すすまない事に気づいたので書き直した
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <set>
#include <map>
#include <list>
#include <queue>
#include <algorithm>
#include <cmath>
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())
main()
{
int T; string s;
cin >> T;
getline(cin,s);
char buf[256];
rep(t,T){
getline(cin,s);
int len = sz(s);
vector<int> d(len);
rep(i,len) d[i] = s[i] - '0';
vector<int> bup(all(d));
next_permutation(all(d));
if (d <= bup) {
buf[len+1] = 0;
buf[0] = '0'; rep(i,len) buf[1+i] = '0'+d[i];
rep(i,len+1) {
if (buf[i]>'0'){
buf[0] = buf[i];
for(int j=1;j<=i;j++) buf[j]='0';
break;
}
}
printf("Case #%d: %s\n", 1+t, buf);
} else {
buf[len] = 0;
rep(i,len) buf[i] = '0'+d[i];
printf("Case #%d: %s\n", 1+t, buf);
}
}
}
C: Square Math
- ネットワークを書くのに時間かかってた
- 2時間半には間に合わず
- 書きかけのコードを以下に晒します
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <set>
#include <map>
#include <list>
#include <queue>
#include <algorithm>
#include <cmath>
#include "cout.h"
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())
class way;
class node {
public:
int id;
int x, y, v;
vector<way*> outlets;
node(int id){
this->x = -1;
this->y = -1;
this->v = -1;
this->id = id;
}
node(int x, int y, int v, int id) {
this->x = x;
this->y = y;
this->v = v;
this->id = id;
}
void addOutlet(way* way) { outlets.pb(way); }
};
class way {
public:
node *from, *to;
int ofs;
char says[3];
way(node *from,node *to,int pm,int ofs) {
this->from = from;
this->to = to;
this->ofs = pm * ofs;
from->addOutlet(this);
says[2] = 0;
says[1] = '0' + ofs;
says[0] = "-=+"[pm+1];
}
};
inline int mag(int ch)
{
return (ch == '+')? 1 : -1;
}
vector<node*> nodes; int node_id = 0;
vector<way*> ways;
typedef pair<int,pair<string,pair<node*,int> > > stat;
inline stat make_stat(int score, string str, node *n, int val)
{
return make_pair(-score,make_pair(str,make_pair(n,val)));
}
inline int stat_score(stat st) { return -st.first; }
inline string stat_str(stat st) { return st.second.first; }
inline node* stat_node(stat st) { return st.second.second.first; }
inline int stat_val(stat st) { return st.second.second.second; }
main()
{
int T;
cin >> T;
rep(t,T){
int W, Q;
cin >> W >> Q;
vector<string> asq;
vector<int> nums(Q,0);
node *root = new node(node_id++);
vector<vector<node*> > nodefind(W,vector<node*>(W,(node*)NULL));
// pass1
rep(y,W){
string s;
cin >> s;
asq.pb(s);
rep(x,W){
if (isdigit(s[x])) {
node *a_node = new node(x,y,s[x]-'0',node_id++);
nodefind[y][x] = a_node;
way *a_way = new way(root,a_node,0,s[x]-'0');
nodes.pb(a_node);
}
}
}
// pass2
tr(nodes,it){
node *me = *it;
//n->x, n->y
int x=me->x, y=me->y, v=me->v;
// printf(" NODE %d at (%d,%d)¥n", v,x,y);
// 上
if (0<y) {
int pm = mag(asq[y-1][x]);
if (1<y) {
//cout << "<nn>" << endl;
node *nn = nodefind[y-2][x];
way *wn = new way(me,nn,pm,nn->v);
ways.pb(wn);
}
if (0<x) {
//cout << "<nw>" << endl;
node *nn = nodefind[y-1][x-1];
way *wn = new way(me,nn,pm,nn->v);
ways.pb(wn);
}
if (x<W-1) {
//cout << "<ne>" << endl;
node *nn = nodefind[y-1][x+1];
way *wn = new way(me,nn,pm,nn->v);
ways.pb(wn);
}
{
//cout << "<ns!>" << endl;
way *wn = new way(me,me,pm,v);
ways.pb(wn);
}
}
// 左
if (0<x) {
int pm = mag(asq[y][x-1]);
if (0<y) {
//cout << "<wn>" << endl;
node *nn = nodefind[y-1][x-1];
way *wn = new way(me,nn,pm,nn->v);
ways.pb(wn);
}
if (1<x) {
//cout << "<ww>" << endl;
node *nn = nodefind[y][x-2];
way *wn = new way(me,nn,pm,nn->v);
ways.pb(wn);
}
{
//cout << "<we!>" << endl;
way *wn = new way(me,me,pm,v);
ways.pb(wn);
}
if (y<W-1) {
//cout << "<ws>" << endl;
node *nn = nodefind[y+1][x-1];
way *wn = new way(me,nn,pm,nn->v);
ways.pb(wn);
}
}
// 右
if (x<W-1) {
int pm = mag(asq[y][x+1]);
if (0<y) {
//cout << "<en>" << endl;
node *nn = nodefind[y-1][x+1];
way *wn = new way(me,nn,pm,nn->v);
ways.pb(wn);
}
{
//cout << "<ew!>" << endl;
way *wn = new way(me,me,pm,v);
ways.pb(wn);
}
if (x<W-2) {
//cout << "<ee>" << endl;
node *nn = nodefind[y][x+2];
way *wn = new way(me,nn,pm,nn->v);
ways.pb(wn);
}
if (y<W-1) {
//cout << "<es>" << endl;
node *nn = nodefind[y+1][x+1];
way *wn = new way(me,nn,pm,nn->v);
ways.pb(wn);
}
}
// 下
if (y<W-1) {
int pm = mag(asq[y+1][x]);
{
//cout << "<sn!>" << endl;
way *wn = new way(me,me,pm,v);
ways.pb(wn);
}
if (0<x) {
//cout << "<sw>" << endl;
node *nn = nodefind[y+1][x-1];
way *wn = new way(me,nn,pm,nn->v);
ways.pb(wn);
}
if (x<W-1) {
//cout << "<se>" << endl;
node *nn = nodefind[y+1][x+1];
way *wn = new way(me,nn,pm,nn->v);
ways.pb(wn);
}
if (y<W-2) {
//cout << "<ss>" << endl;
node *nn = nodefind[y+2][x];
way *wn = new way(me,nn,pm,nn->v);
ways.pb(wn);
}
}
}
rep(q,Q) cin >> nums[q];
cout << "square: " << asq;
cout << "nums: " << nums << endl;
/*
cout << "nodes: " << sz(nodes) << endl;
tr(nodes,it) {
node *n = *it;
printf(" : node#%d, value=%d at (%d,%d)¥n", n->id, n->v, n->x, n->y);
}
cout << "ways: " << sz(ways) << endl;
tr(ways,it) {
way *w = *it;
printf(" : %s to node#%d¥n", w->says, w->to->id);
}
*/
//cout << "nums: " << nums << endl;
printf("Case #%d:¥n", 1+t);
tr(nums,nt) {
int target = *nt;
priority_queue<stat> pq;
// pair<int,pair<string,pair<node*,int> > > >
pq.push( make_stat(target,"",root,0) );
while (!pq.empty()) {
stat s = pq.top(); pq.pop();
int sc = stat_score(s), v = stat_val(s);
node *n = stat_node(s);
if (sc == 0) {
//printf("now on node#%d, '%s', value=%d¥n", n->id, stat_str(s).c_str(), v);
//continue;
cout << stat_str(s) << endl;
break;
}
tr(n->outlets,it){
way *w = *it;
int v_ = v + w->ofs;
pq.push( make_stat(abs(v_-target), stat_str(s) + w->says, w->to, v_) );
}
}
}
}
}
試合後投稿
- practice roomが開いたらとりあえずsubmitしてみた
- Aはすんなり通過
- BはLargeが重くてひっかかったので書き直し+再実行も含め5分ぐらい
- 2問分のコーディングに50分前後、投稿に5分前後かかったので180位相当。このRound 1Bに出てても余裕で通過できたっぽい
コメント
トラックバック - https://topcoder-g-hatena-ne-jp.jag-icpc.org/n4_t/20090913