AOJ2032 Online Quiz System
問題リンク Online Quiz System
- 概要
オンラインクイズゲームシステムのシミュレートを行い、サーバとクライアント間のデータ通信量を答えよ。
プレイヤー数はM、問題数はNである。
クライアント側のプログラムは全て同じである。
全問題文は事前にダウンロードされており、このデータ通信量はシミュレートに含めなくてよい。
システムは次のように動く
最初の問題文が表示される。プレイヤーは制限時間内に解答する。その後2番目の問題が表示される。これがN問繰り返される。N問繰り返されたらゲームが終了する。
各問題フェーズでは、プレイヤーは他のプレイヤーに関する情報が送信される。
プレイヤーが解答提出をしていない場合: 解答した人物が通知される
プレイヤーが解答提出を済ませている場合: 他の人がなんという解答をしたかが通知される
各問題フェーズが始まるとき、サーバは a synchronization packet for problem-start を全プレイヤーに送り、同時にポーリングを開始する。ポーリング開始から1000ms毎に、サーバはその時刻以前(strictly)にプレイヤーから解答を受け取っていないかを調べる。あれば全プレイヤーに次のような通知を送る。
解答未提出のプレイヤー: 新たにサーバが受け取った分に関して、notificaton packet type Aを送る
新たに解答を提出したプレイヤー: 厳密にこの時間以前に受け取った分に関して、他人の解答をnotificaton packet type Bにて送る。このパケットに自分自身の解答は含まれない
解答提出済みのプレイヤー: 新たにサーバが受け取った分に関して、notification packet type Bを送る
これらのパケットには他人の情報が1件以上含まれていなければならない。さもなければ、そのパケットは破棄される。
a synchronization packet for problem-startが送られてから20000ms経ったとき、必要ならtype A, type Bのパケットを送信したあと、problem-endパケットを全プレイヤーに送り、その問題を終了する。
プレイヤーはproblem-startを受け取った後、problem-endを受け取るまで、answer packetを送って解答を送ることができる。
1 <= M, N <= 100
- 解法
シミュレーションをがんばります。
ただこの問題はちょっとひどい所があって、遅延についてほとんど説明がないことです。
入力の説明を見ると急に、クライアント毎にdelay timeという値があるのですが、これがシミュレートにどう影響を及ぼすか書かれていないのです。いや、問題文の最初の方に、「In particular, much attention should be paid to the delay on receiving packets.」と書いてあることはあるんですが、シミュレート問題なんだからもっと具体的に書いておいて欲しかった。
結論からいうと、遅延はサーバから送信するときと受信するとき、両方で起こります。これを踏まえて入力で
P T A
と来たときを考えてみます。Tはクライアントがproblem-startを受け取ってからサーバへ送信したときのクライアント側の時間のことです。クライアントはこのproblem-startを受信するときに既にD遅延しており、サーバへ送信するときに更にDだけ遅延するので、結局、サーバ内時間で、この解答パケットを受け取るのはT + 2*Dになります。このことさえ気を付ければあとはシミュレートをガリガリ書くだけだと思います。
- ソース
import java.util.Arrays; import java.util.PriorityQueue; import java.util.Scanner; //Online Quiz System public class AOJ2032 { int WORK = 0, START = 1, END = 2, SUBMIT = 3; class E implements Comparable<E>{ int type, t, id; public E(int type, int t, int id) { this.type = type; this.t = t; this.id = id; } public int compareTo(E o) { return t!=o.t?t-o.t:type-o.type; } } void run(){ Scanner sc = new Scanner(System.in); boolean[] just = new boolean[100], sub = new boolean[100]; int[] L = new int[100], send = new int[100], rev = new int[100], delay = new int[100]; for(boolean H=true;;H=false){ int M = sc.nextInt(), N = sc.nextInt(); if((M|N)==0)break; if(!H)System.out.println(); Arrays.fill(send, 0); Arrays.fill(rev, 0); for(int i=0;i<M;i++)delay[i]=sc.nextInt(); while(N--!=0){ Arrays.fill(L, 0); Arrays.fill(just, false); Arrays.fill(sub, false); PriorityQueue<E> q = new PriorityQueue<E>(); q.add(new E(START, 0, -1)); q.add(new E(END, 20000, -1)); for(int t=1000;t<=20000;t+=1000)q.add(new E(WORK, t, -1)); int k = sc.nextInt(); while(k--!=0){ int id = sc.nextInt(), t = sc.nextInt(), len = sc.next().length(); q.add(new E(SUBMIT, t+delay[id]*2, id)); L[id] = len; } while(!q.isEmpty()){ E e = q.poll(); if(e.type==START){ for(int i=0;i<M;i++)rev[i]+=3; } else if(e.type==END){ for(int i=0;i<M;i++)rev[i]+=4; break; } else if(e.type==SUBMIT){ just[e.id] = sub[e.id] = true; send[e.id] += 5+L[e.id]; } else{ int newly = 0, submit = 0, allsize = 0, newlysize = 0; for(int i=0;i<M;i++){ if(just[i])newly++; if(just[i])newlysize+=L[i]; if(sub[i])submit++; if(sub[i])allsize+=L[i]; } for(int i=0;i<M;i++){ if(!sub[i]){ if(0<newly){ rev[i]+=4+newly; } } else if(just[i]){ if(1<submit){ rev[i]+=4+2*(submit-1)+allsize-L[i]; } } else{ if(0<newly){ rev[i]+=4+2*newly+newlysize; } } } Arrays.fill(just, false); } } } int ress = 0, resr = 0; for(int i=0;i<M;i++){ ress+=rev[i]; resr+=send[i]; } System.out.println(ress+" "+resr); for(int i=0;i<M;i++)System.out.println(send[i]+" "+rev[i]); } } public static void main(String[] args) { new AOJ2032().run(); } }