HDU 5132

#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <set>
#include <algorithm>

const int MAXN = 11;
const double EPS = 1e-8;

inline int SGN(double x) {
	return (x > EPS) - (x < -EPS);
}

struct Setion {
	double ti;
	int dr;
	std::set< int > ban; // record the index of train which is waiting
} S[MAXN];

struct C_Time {
	double ti;
	int idx; // train index
	int dr; // train running direction
	bool operator< (C_Time t) const {
		return t.ti < ti;
	}
} tmp;

bool vis[MAXN]; // ready to depart
int st[MAXN], ans[MAXN], di[MAXN], sp[MAXN];

int main() {
	int c, n, m;
	double s;
	scanf("%d",&c);
	while (c--) {
		scanf("%d%d%lf", &n, &m, &s);
		for (int i = 0; i <= n; ++i) {
			S[i].ti = 0.0;
			S[i].dr = 0;
			S[i].ban.clear();
		}
		std::priority_queue< C_Time > pq;
		for (int i = 1; i <= m; ++i) {
			scanf("%d%d%lf%d", st + i, di + i, &tmp.ti, sp + i);
			tmp.idx = i;
			tmp.dr = 0;
			pq.push(tmp);
			vis[i] = false;
		}
		while (!pq.empty()) {
			C_Time cur;
			do {
				cur = pq.top();
				pq.pop();
				if (cur.dr == 1) --S[st[cur.idx]].dr;
				else if(cur.dr == -1) ++S[st[cur.idx] + 1].dr;
				if(st[cur.idx] == di[cur.idx])
					ans[cur.idx] = ceil(cur.ti);
				else
					vis[cur.idx] = true;
			} while (!pq.empty() && !SGN(pq.top().ti - cur.ti));
			for (int i = 1; i <= m; ++i) {
				if (!vis[i])
					continue;
				tmp.idx = i;
				int tmp_di = st[i] + (di[i] > st[i]); // the index of section
				if (!(S[tmp_di].ban.empty()) && *(S[tmp_di].ban.begin()) < i) // if the train with smaller index is waiting
					tmp.dr = 0;
				else if (di[i] < st[i])
					tmp.dr = S[tmp_di].dr > 0 ? 0 : -1;
				else
					tmp.dr = S[tmp_di].dr < 0 ? 0 : 1;
				if (tmp.dr) {
					S[tmp_di].ti = tmp.ti = std::max(cur.ti + s / sp[i], S[tmp_di].ti);
					S[tmp_di].dr += tmp.dr;
					st[i] += tmp.dr;
					S[tmp_di].ban.erase(i);
				} else {
					S[tmp_di].ban.insert(i); // This train will wait
					tmp.ti = S[tmp_di].ti;
				}
				pq.push(tmp);
				vis[i] = false;
			}
		}
		for(int i = 1; i <= m; ++i)
			printf("%d\n", ans[i]);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值