Electric Car Rally--最短路SPFA

In an attempt to demonstrate the practicality of electric cars, ElecCarCo is sponsoring a cross-country road rally. There are n charging stations for the rally where cars may check in and charge their batteries
The rally may require multiple days of travel. Each car can travel four hours (240 minutes) between charges. A car must be plugged into a charger for two minutes for each minute of travel time. Cars start the rally at noon on the first day, fully charged. Cars are permitted remain at a station even after they are fully charged.
It is only possible to drive directly between select pairs of stations. Variations in traffic conditions, road conditions, availability of HOV lanes, etc., result in different travel times along each route depending upon the time of day at which travel along that route begins. All roads are two-way, and the prevailing conditions affect travel in both directions.
The winner is the first car to reach checkpoint n-1, starting form checkpoint 0. Other than the starting and ending conditions, cars may pass through the stations in any order, and need not visit all stations to complete the course.
Write a program to determine the earliest time, expressed as the total number of minutes elapsed since the start of the rally, at which a car could reach the final checkpoint.
The Input
There will be several test cases in the input. Each test case starts with a line containing n (1≤n≤500), the number of stations, and m (1≤m≤1,000), the number of connecting road segments.
This is followed by m blocks, each block describing one road segment. A road segment block has the following structure:
Each block begins with a single line containing two integers, a and b (0≤a,b≤n-1, a≠b). These numbers are the two checkpoints connected by that segment. The connections are undirected: a segment permitting travel from station a to station b will also allow travel from station b to station a.
This is followed by from one to twenty 'travel lines' describing travel times. Each of the travel lines contains 3 numbers: Start, Stop, (0≤Start<Stop≤1,439), and Time (0<Time<1,000). Start and Stop are the time of day (expressed in minutes since midnight) described by this line, and Time is the travel time, in minutes, required to traverse this road segment if travel begins at any time in the range [Start..Stop], inclusive. The first travel line in a block will have a start time of 0 (midnight, or 00:00). The final travel line in a block will have a stop time of 1439 (i.e., 23:59, or 1 less than 24hours times 60 minutes). Adjacent travel lines in the input will be arranged in order, and the start time of any line after the first is one higher than the stop time of the preceding line. The travel lines will cover all times from 00:00 to 23:59.
Input will end with a line with two 0s. All test cases will describe a course that can be completed by the cars.
The Output
For each test case, output a single integer representing the smallest number of minutes needed to complete the rally. Output no spaces, and do not separate answers with blank lines.

hours times 60 minutes). Adjacent travel lines in the input will be arranged in order, and the start time of any line after the first is one higher than the stop time of the preceding line. The travel lines will cover all times from 00:00 to 23:59.
Input will end with a line with two 0s. All test cases will describe a course that can be completed by the cars.
The Output
For each test case, output a single integer representing the smallest number of minutes needed to complete the rally. Output no spaces, and do not separate answers with blank lines.

题意:

求从0到N-1城市的最短路。汽车最多能跑240min。充电2分钟能跑一分钟。

每条道路每天分成多个时间段,每个时间段的行驶时间不同。

dp[i][j]表示第i个城市,剩下j的电的最短时间。

湖南多校对抗赛的一道题目,原题是美国regional的。!!
万万没想到人生第一个FB就这样来了。。。而且全场只有一个提交啊!!想想还有点小激动。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
#define inf 0x3f3f3f3f
#define maxn 520
#define maxm 40080
int dp[maxn][maxn],first[maxn];
int vv[maxm],ss[maxm],tt[maxm],ww[maxm],nxt[maxm];
int e,n,m,ans;
void init()
{
	e = 0;
	memset(first,-1,sizeof(first));
	ans = inf;
	for(int i = 0;i < n;i++)
		memset(dp[i],0x3f,sizeof(dp[i]));
	dp[0][480] = 0;
}

struct State
{
	int u,lef,t;
	State(){}
	State(int uu,int ll,int tt)
	{
		u = uu;
		lef = ll;
		t = tt;
	}
	bool operator < (const State & a) const
	{
		return t > a.t;
	}
};

priority_queue <State> q;
void Addedge(int u,int v,int s,int t,int cost)
{
	if(cost > 240)	return;
	vv[e] = v;ss[e] = s;tt[e] = t;ww[e] = cost*2;
	nxt[e] = first[u];first[u] = e++;
	vv[e] = u;ss[e] = s;tt[e] = t;ww[e] = cost*2;
	nxt[e] = first[v];first[v] = e++;
}

inline int min(int a,int b)
{
	return a>b?b:a;
}

int main()
{
	freopen("in.txt","r",stdin);
	while(scanf("%d%d",&n,&m)==2 && (n||m))
	{
		init();
		for(int i = 0;i < m;i++)
		{
			int u,v;
			scanf("%d%d",&u,&v);
			int ns = 0,nt = 0,nw = 0;
			while(1)
			{
				scanf("%d%d%d",&ns,&nt,&nw);
				Addedge(u,v,ns,nt,nw);
				if(nt == 1439)	break;
			}
		}
		while(!q.empty())	q.pop();
		q.push(State(0,480,0));
		while(!q.empty())
		{
			State nowstate = q.top();
			q.pop();
			if(nowstate.t >= ans)	break;
			int u = nowstate.u,lef = nowstate.lef,t = nowstate.t;
			if(u == n-1)	
			{
				ans = min(ans,t);
				break;
			}
			int modt = (t+720)%1440;
			for(int i = first[u];i != -1;i = nxt[i])
			{
				if(modt >= ss[i] && modt <= tt[i] && lef >= ww[i])//直接走
				{
					if(dp[vv[i]][lef-ww[i]] > t + ww[i]/2)
					{
						q.push(State(vv[i],lef-ww[i],t+ww[i]/2));
						dp[vv[i]][lef-ww[i]] = t+ww[i]/2;
					}
				}
				else //不能直接走
				{
					int elef = lef,et = t;
					if(elef < ww[i])//油不够
					{
						et += ww[i] - elef;
						elef = ww[i];
					}
					int emodt = (et+720)%1440;
					if(emodt >= ss[i] && emodt <= tt[i])//如果油加够的时候在这个时间段内,直接跑
					{
						if(dp[vv[i]][elef - ww[i]] > et + ww[i]/2)
						{
							q.push(State(vv[i],elef-ww[i],et+ww[i]/2));
							dp[vv[i]][elef-ww[i]] = et + ww[i]/2;
						}
					}
					else
					{
						int addt = ss[i] - emodt;
						if(addt < 0)	addt += 1440;
						et += addt;
						elef += addt;
						if(elef >= 480) elef = 480;
						if(dp[vv[i]][elef-ww[i]] > et + ww[i]/2)
						{
							q.push(State(vv[i],elef-ww[i],et+ww[i]/2));
							dp[vv[i]][elef-ww[i]] = et+ww[i]/2;
						}
					}
				}
			}
		}
	}
	return 0;
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值