EOJ:Crossing the Road

——从地图左下角到右上角需要最短的时间(有交通灯)

——搜索

——url:http://202.120.106.94/onlinejudge/problemshow.php?pro_id=446

——source:Google Code Jam

————————————————————————————————————————————————

一开始以为只可能往上和往右走,于是直接DP。

事实上由于红灯时间很长,可以绕个来回。

本题灯的熄灭时间存储比较麻烦

另外算路口通过的时间是用求模运算会快很多

#include<stdio.h>
#include<queue>
using namespace std;
#define MAXM 100
#define oo 100000000000000000LL
const int dx[4] =
{ 0, 1, 0, -1 };
const int dy[4] =
{ 1, 0, -1, 0 };
struct node
{
	int x, y;
	long long t;
	bool operator <(const node &b) const
	{
		return t > b.t;
	}
	node()
	{

	}
	node(int a, long long b, long long c)
	{
		x = a;
		y = b;
		t = c;
	}
} u, v;
long long T[MAXM][MAXM];
long long TIME[MAXM][MAXM][3];
int n, m, C;
void readin()
{
	int i, j, k;
	scanf("%d%d", &n, &m);
	for (i = 0; i < n; i++)
		for (j = 0; j < m; j++)
		{
			for (k = 0; k < 3; k++)
				scanf("%lld", &TIME[n - i - 1][j][k]);
			TIME[n - i - 1][j][2] %= (TIME[n - i - 1][j][0]
					+ TIME[n - i - 1][j][1]);
		}

}
long long min(long a, long long b)
{
	return a < b ? a : b;
}
void work()
{
	int i, j;
	long long N, W, t, tmp;
	priority_queue<node> q;
	for (i = 0; i <= 2 * n; i++)
		for (j = 0; j <= 2 * m; j++)
			T[i][j] = oo;
	T[0][0] = 0;
	q.push(node(0, 0, 0));
	while (!q.empty())
	{
		u = q.top();
		q.pop();
		if (u.t > T[u.x][u.y])
			continue;
		if (u.x == 2 * n - 1 && u.y == 2 * m - 1)
			break;
		N = TIME[u.x / 2][u.y / 2][0];
		W = TIME[u.x / 2][u.y / 2][1];
		t = TIME[u.x / 2][u.y / 2][2];
		for (i = 0; i < 4; i++)
		{
			v.x = u.x + dx[i];
			v.y = u.y + dy[i];
			if (v.x < 0 || v.x >= 2 * n || v.y < 0 || v.y >= 2 * m)
				continue;
			if (((u.y % 2 == 1) && (i == 0)) || ((v.y % 2 == 1) && (i == 2))   //不过马路
					|| ((u.x % 2 == 1) && (i == 1)) || ((v.x % 2 == 1) && (i
					== 3)))
				v.t = u.t + 2;
			else if (i == 1 || i == 3)
			{
				tmp = t;
				tmp = (tmp - (u.t) % (N + W) + N + W) % (N + W) + u.t;    //过马路南北方向走
				if (tmp - (N + W) <= u.t && tmp - W >= u.t + 1)
					v.t = u.t + 1;
				else if (N >= 1)
					v.t = tmp + 1;
			}
			else
			{
				tmp = t + N;
				tmp = (tmp - (u.t) % (N + W) + N + W) % (N + W) + u.t;    //过马路东西方向走
				if (tmp - (N + W) <= u.t && tmp - N >= u.t + 1)
					v.t = u.t + 1;
				else if (W >= 1)
					v.t = tmp + 1;
			}
			if (v.t < T[v.x][v.y])
			{
				T[v.x][v.y] = v.t;
				q.push(v);
			}

		}
	}
	printf("%lld\n", T[2 * n - 1][2 * m - 1]);
}
int main()
{
	int i;
	scanf("%d", &C);
	for (i = 1; i <= C; i++)
	{
		readin();
		printf("Case #%d: ", i);
		work();
	}
	return 0;
}

  

posted on 2011-07-26 21:24  风也轻云也淡  阅读(129)  评论(0编辑  收藏  举报