Problem:
Data Center on Fire

今から少し未来の話である．高密度記憶および長期保存可能である記録デバイスが開発されてきたが，コンテンツが生み出される速度が異常なほどに速かったため，データセンターを設立した．データセンターを設立した当初は小さな建物だったが，増え続けるデータにあわせて何度も拡張工事をしたため，性能の異なるエレベータを何基も持つこととなった．

ところが，データセンターで火災が発生した．火は一定時間だけ経過すると上の階ないし下の階に燃え広がる．また，火がついてから一定時間だけ経過するとその階は焼失してしまう．そこでエレベータを使ってデバイスを運び出すこととした．このエレベータは耐火性能が完璧であるため，階の焼失に関わらず任意の階へ移動できる．また，非常に強力な加速減速装置を持つことから，加速および減速にかかる時間は無視できるほど小さいため，一瞬にして定常速度に加速すること，あるいは停止することができる．また，緊急時においてはいわゆる「開」ボタンが機能しないようにプログラムされているため，エレベータの停止時間は運び出す（あるいは降ろす）デバイスの個数にかかわらず一定である．また，階の焼失前に到着したエレベータによって運び出されるデバイスについては，たとえエレベータの出発前に階が焼失したとしても，焼失の影響を受けない．ただし，エレベータに乗せることができなかったデバイスは当然ながら焼失する．

エレベータはどの階から回収してよいか分からないため，デバイスのある最上階を目指すようにプログラムされている．ただし，エレベータ同士は通信可能であり，別のエレベータが目的階に到着した瞬間に情報が通信される．到着したエレベータに全てのデバイスが積みこめることがわかったときは，目的階よりも下にあり，回収可能なデバイスが残っている階のうちで最上階に目的階を変更する．また，焼失のために目的階に向かう必要性が失われたときも，同様にして目的階を変更する．目的階を変更するときに，移動方向を変更する必要があるときは，即座に移動方向を変更する．また，エレベータが満杯になってそれ以上のデバイスを積みこむことができないとき，あるいは回収可能なデバイスが残っていないときは 1 階を目指す．

あなたの仕事は，上記の条件のもとで，退避させることのできたデバイスの個数および到着時刻を求めるプログラムを作成することである．

Input

入力は複数のデータセットから構成される．それぞれのデータセットは次の形式で与えられる．

N M

d

n1 n2 ... nN

c1 v1 ts1 x1

c2 v2 ts2 x2

...

cM vM tsM xM
k tx ty tz

記号の意味は次のとおりである．入力中の値はすべて整数である．

N (2 <= N <= 30)，M (1 <= M <= 10)はそれぞれビルの階数，エレベータの基数を表す．

d (1000 <= d <= 10000)は階と階の間の距離を表す．

ni (0 <= ni <= 100) は i 階にあるデバイスの個数を表す．

ci (1 <= ci <= 50)，vi (1 <= vi <= 2000)，tsi (1 <= tsi <= 20)，xi (1 <= xi <= N)はそれぞれ i 番目のエレベータの容量，速度，停止時間，初期位置をあらわす．初期位置は何階にあるかで表される．

k (2 <= k <= N)，tx (30 <= tx <= 300)，ty (30 <= ty <= 300)，tz (30 <= tz <= 300)はそれぞれ火元の階，火がついてから焼失するまでの時間，上に燃え移るまでの時間，下に燃え移るまでの時間を表す．

入力の終了は 2 つの 0 を含む行によってあらわされる．これはデータセットの一部ではない．

それぞれのデータセットは次の条件を満たすと仮定してよい．

単位時間の 1/1000 よりも短い時間の間に複数の階の消失が起こることはない．

単位時間の 1/1000 よりも短い時間の間に複数のエレベータが同一の階で 1 階より上にある階に到着することない．

単位時間の 1/1000 よりも短い時間の間にエレベータの到着とそのエレベータが到着しようとした階の焼失が起こることはない．

Output

それぞれのテストケースについて，回収されたデバイスの個数，および最後に回収されたデバイスが 1 階に到着してエレベータから降ろされるまでの時間を，単一の空白で区切って 1 行で出力しなさい．ただし，時間については，小数点以下に何個の数字を出力しても構わないが，0.001 を超える誤差を含めてはならない．また，1 階にあるデバイス以外は回収できなかったときは時間としてゼロを出力しなさい．

Sample Input

5 2
5000
10 20 0 30 5
10 1000 6 1
20 500 8 1
3 40 25 30
0 0

Output for the Sample Input

50 84.000

Solution in JAVA (judge verdict: Wrong Answer)

import java.util.PriorityQueue;
import java.util.Scanner;

//Data Center on Fire
public class Main{

	final int NONE = 0, GO = 1, CLOSE = 2, BACK = 3, FIRE = 4;
	class E{
		int id, cap, stop, c, state, tar;
		double pos, v;
		public E(int id, int cap, int stop, double pos, double v) {
			this.id = id;
			this.cap = cap;
			this.stop = stop;
			this.pos = pos;
			this.v = v;
		}
	}
	class R implements Comparable<R>{
		int event, p;
		double t;
		public R(int event, int p, double t) {
			this.event = event;
			this.p = p;
			this.t = t;
		}
		public int compareTo(R o) {
			return (int)Math.signum(t-o.t);
		}
	}

	int N, M, target;
	double[] fh;
	int[] dev;
	E[] es;
	boolean ex;

	void next(){
		while(target>1&&dev[target]==0)target--;
	}
	boolean con(){
		if(target>1)return true;
		for(int i=0;i<M;i++)if(es[i].state!=NONE)return true;
		return false;
	}

	void run(){
		Scanner sc = new Scanner(System.in);
		for(;;){
			N = sc.nextInt(); M = sc.nextInt();
			if((N|M)==0)break;
			target = N; ex = false;
			int H = sc.nextInt();
			fh = new double[N+1];
			for(int i=1;i<=N;i++)fh[i]=(i-1)*H;
			dev = new int[N+1];
			for(int i=1;i<=N;i++)dev[i]=sc.nextInt();
			next();
			es = new E[M];
			for(int i=0;i<M;i++){
				int c = sc.nextInt(), v = sc.nextInt(), stop = sc.nextInt(), x = sc.nextInt();
				es[i] = new E(i, c, stop, fh[x], v);
			}
			PriorityQueue<R> q = new PriorityQueue<R>();
			int[] fire = new int[N+1];
			int K = sc.nextInt(), tf = sc.nextInt(), tup = sc.nextInt(), tdn = sc.nextInt();
			for(int i=K-1;i>0;i--)fire[i]=fire[i+1]+tdn;
			for(int i=K+1;i<=N;i++)fire[i]=fire[i-1]+tup;
			for(int i=1;i<=N;i++)q.add(new R(FIRE, i, fire[i]+tf));
			for(int i=0;i<M;i++){
				if(target==1)es[i].state = NONE;
				else{
					es[i].state = GO; es[i].tar = target;
				}
			}
			int res = dev[1]; dev[1] = 0;
			double t = 0, anst = 0;
			while(con()){
				int id = -1;
				double min = 1<<29;
				for(int i=0;i<M;i++){
					if(es[i].state!=GO)continue;
					double dt = t + Math.abs(fh[es[i].tar]-es[i].pos)/es[i].v;
					if(dt<min){
						min = dt; id = i;
					}
				}
				if(id!=-1&&(q.isEmpty()||!q.isEmpty()&&min<q.peek().t)){
//					System.out.println("Reach:"+id+" on:"+es[id].tar+" dev:"+dev[es[id].tar]+" at:"+min);
					double dt = min-t;
					for(int i=0;i<M;i++){
						if(es[i].state!=GO)continue;
						if(fh[es[i].tar]<es[i].pos)es[i].pos-=es[i].v*dt;
						else es[i].pos+=es[i].v*dt;
					}
					int carry = Math.min(dev[es[id].tar], es[id].cap-es[id].c);
					es[id].c += carry;
					es[id].state = CLOSE;
					q.add(new R(CLOSE, id, min+es[id].stop));
					dev[es[id].tar] -= carry;
//					System.out.println("Ev:"+id+" "+es[id].c+"/"+es[id].cap+" Floor rest:"+dev[es[id].tar]);
					if(dev[es[id].tar]==0){
						next();
						if(target>1){
							for(int i=0;i<M;i++){
								if(es[i].state!=GO)continue;
								es[i].tar = target;
							}
						}
						else{
							for(int i=0;i<M;i++){
								if(es[i].state!=GO)continue;
								if(es[i].c==0)es[i].state = NONE;
								else {
									es[i].state = BACK;
									q.add(new R(BACK, i, min+es[i].pos/es[i].v));
								}
							}
						}
					}
					t = min;
				}
				else{
					R r = q.poll();
					double dt = r.t-t;
					for(int i=0;i<M;i++){
						if(es[i].state!=GO)continue;
						if(fh[es[i].tar]<es[i].pos)es[i].pos-=es[i].v*dt;
						else es[i].pos+=es[i].v*dt;
					}
					if(r.event==CLOSE){
//						System.out.println("Close :"+r.p+" at:"+r.t);
						if(es[r.p].tar==1){
							anst = r.t;
							ex = true;
							if(target>1){
								es[r.p].state = GO;
								es[r.p].tar = target;
							}
							else es[r.p].state = NONE;
						}
						else{
							if(es[r.p].c==es[r.p].cap){
								es[r.p].state = BACK;
								es[r.p].tar = 1;
								q.add(new R(BACK, r.p, r.t+es[r.p].pos/es[r.p].v));
							}
							else{
								if(target>1){
									es[r.p].state = GO; es[r.p].tar = target;
								}
								else{
									es[r.p].state = BACK;
									es[r.p].tar = 1;
									q.add(new R(BACK, r.p, r.t+es[r.p].pos/es[r.p].v));
								}
							}
						}
					}
					else if(r.event==BACK){
//						System.out.println("Back: "+r.p+" at:"+r.t+" with:"+es[r.p].c);
						es[r.p].pos = 0;
						res += es[r.p].c; es[r.p].c = 0;
						es[r.p].state = CLOSE;
						q.add(new R(CLOSE, r.p, r.t+es[r.p].stop));
					}
					else if(r.event==FIRE){
//						System.out.println("Fire on:"+r.p+" at:"+r.t);
						dev[r.p] = 0;
						next();
						for(int i=0;i<M;i++){
							if(es[i].state!=GO)continue;
							if(target>1)es[i].tar = target;
							else{
								if(es[i].c==0)es[i].state=NONE;
								else{
									es[i].state = BACK; es[i].tar = 1;
									q.add(new R(BACK, i, r.t+es[i].pos/es[i].v));
								}
							}
						}
					}
					t = r.t;
				}
			}
			System.out.printf("%d %.3f\n", res, anst);
		}
	}

	public static void main(String[] args) {
		new Main().run();
	}
}