このあたりから本番かな。small/large両方あるしね。
Google社員とダンスをするというシャレ乙な問題。
ただ、一般人がダンスするだけなのにスコア付けされるのかよ。
さてさて。
入力は3人の審査委員の点数の合計なのですが、3人の意見はいつも均衡に近い状況で、点差が3以上になることはないんだそうです。
つまり、合計点が15点なら(5,5,5)または(4,5,6)な感じで点数の組が分かれます。
もし、2点以上というか2点の差があれば"surprise"な組だと。
これって審査員談合してね?
surpriseな組の点数は合計をnとして、
n ≡ 0 (mod 3)なら: (floor(n/3)-1, floor(n/3), floor(n/3)+1)
n ≡ 2 (mod 3)なら: (floor(n/3), floor(n/3), floor(n/3)+2)
である。 n ≡ 1 (mod 3)ならsurpriseになりえない。
surpriseじゃない組も同じ感じで静的に求められる。
それぞれ、 make_triplet_surprise()と make_triplet_not_surprise()である。
main()の動きとしては、
- はじめ全ての点数を"not surprise"な組にしておく。
- 合計点の高いほうから順にS個を"surprise"な組にし直す。("surprise"にできないならほっとく。)
- is_above_p()を使って組の点数全てがpを超えている組をカウントする。
コード全文は以下のような感じで。
#include <cstdio> #include <cstdlib> #include <cstring> #include <list> #include <algorithm> #include <functional> #define CAN_SURPRISE(t) ((t) ? (((t - ((t/3)*3))-1) ? 1 : 0) : 0) typedef struct _Triplet{ unsigned int t; unsigned int triplet[3]; } Triplet; bool compareTriplet(Triplet &a, Triplet &b) { return a.t > b.t; } void make_triplet_not_surprise(unsigned int t, unsigned int* triplet) { unsigned int avg = t / 3; switch(t - (avg * 3)) { case 0: triplet[0] = triplet[1] = triplet[2] = avg; break; case 1: triplet[0] = avg+1; triplet[1] = triplet[2] = avg; break; case 2: triplet[0] = triplet[1] = avg+1; triplet[2] = avg; break; } } void make_triplet_surprise(unsigned int t, unsigned int* triplet) { int avg = t / 3; switch(t - (avg * 3)) { case 0: triplet[0] = avg+1; triplet[1] = avg; triplet[2] = avg-1; break; case 2: triplet[0] = avg+2; triplet[1] = triplet[2] = avg; break; } } int is_above_p(unsigned int p, unsigned int *triplet) { return ((triplet[0] >= p) || (triplet[1] >= p) || (triplet[2] >= p)) ? 1 : 0; } int main(int argc, char** argv) { unsigned int T, N, S, p, i, j, temp; unsigned int trip[3]; //FILE *fp = fopen("input.txt","r"); //FILE *fp = fopen("B-small-attempt0.in","r"); FILE *fp = fopen("B-large.in","r"); fscanf(fp, "%d\r\n", &T); for(j=0; j<T; ++j) { std::list<Triplet> t; std::list<Triplet>::iterator t_itr; fscanf(fp, "%d %d %d", &N, &S, &p); for(i=0; i<N; ++i) { fscanf(fp, "%d", &temp); make_triplet_not_surprise(temp, trip); Triplet tr; tr.t = temp; memmove(tr.triplet, trip, 3*sizeof(unsigned int)); t.push_back(tr); } t.sort(compareTriplet); for(t_itr=t.begin(); t_itr!=t.end(); ++t_itr) { if(!is_above_p(p, t_itr->triplet) && CAN_SURPRISE(t_itr->t)) { if(S == 0) break; make_triplet_surprise(t_itr->t, t_itr->triplet); --S; } } temp = 0; for(t_itr=t.begin(); t_itr!=t.end(); ++t_itr) { if(is_above_p(p, t_itr->triplet)) ++temp; } printf("Case #%d: %d\n", j+1, temp); } fclose(fp); return EXIT_SUCCESS; }
まぁこれもそんな難しくはないかな。
0 件のコメント:
コメントを投稿