POJ 2502 Dijkstra

这道题主要麻烦在信号的等待上 写着写着容易混乱

基本思想就是Dijkstra 


#include <iostream>

#define MAXN 305
#define INF (1 << 28)

int map[MAXN][MAXN];
int dist[MAXN];
int v[MAXN];

int M, N;

struct node
{
	int color;
	int r;
	int t[2];
}p[MAXN];

int state(int k, int t, int &r)
{
	if(t < p[k].r)
	{
		r = p[k].r - t;
		return p[k].color;
	}

	t = (t - p[k].r) % (p[k].t[0] + p[k].t[1]);
	//每个点初始信号不通 这里用异或得到下一个状态的颜色
	int c = p[k].color ^ 1;

	if(p[k].t[c] > t)
	{
		r = p[k].t[c] - t;
		return c;
	}
	else
	{
		r = p[k].t[c] + p[k].t[c ^ 1] - t;
		return c ^ 1;
	}
};

int wait(int from, int to, int t)
{
	int r1, r2;
	int c1 = state(from, t, r1);
	int c2 = state(to, t, r2);

	if(c1 == c2)
		return 0;

	if(r1 != r2)
		return r1 < r2 ? r1: r2;

	if(p[from].t[c1 ^ 1] < p[to].t[c2 ^ 1])
		return r1 + p[from].t[c1 ^ 1];
	else if(p[from].t[c1 ^ 1] > p[to].t[c2 ^ 1])
		return r2 + p[to].t[c2 ^ 1];
	else 
		return -1;
};

int Dij(int start, int end)
{
	for(int i = 1; i <= N; i++)
	{
		dist[i] = INF;
		v[i] = false;
	}

	dist[start] = 0;

	int k;
	int f = -1;
	
	while(f != INF)
	{
		f = INF;
		for(int i = 1; i <= N; i++)
		{
			if(!v[i] && dist[i] < f)
			{
				f = dist[i];
				k = i;
			}
		}

		v[k] = true;

		for(int i = 1; i <= N; i++)
		{
			int tm = wait(k, i, dist[k]);
			if(tm == -1)
				continue;
			if(!v[i] && map[k][i] && dist[i] > tm + dist[k] + map[k][i])
			{
				dist[i] = tm + dist[k] + map[k][i];
			}
		}
	}

	return dist[end] >= INF ? 0: dist[end];
};



int main()
{
	int start, end;
	std::cin >> start >> end;

	std::cin >> N >> M;

	int i = 1;
	char sig;
	while(i <= N)
	{
		std::cin >> sig >> p[i].r >> p[i].t[0] >> p[i].t[1];
		if(sig == 'B')
			p[i].color = 0;
		else
			p[i].color = 1;

		i++;
	}

	i = 1;
	int u, v, dur;

	memset(map, 0, sizeof(map));
	while(i <= M)
	{
		std::cin >> u >> v >> dur;
		map[u][v] = map[v][u] = dur;
		i++;
	}

	int res = Dij(start, end);

	std::cout << res << "\n";

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值