UVa 1025 A Spy in the Metro

探讨了在特定条件下,如何在地铁系统中找到从起点到终点的最短等待时间路径,利用动态规划解决列车调度问题,确保角色Mario在躲避间谍的过程中,尽可能减少在车站的停留时间。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:A Spy in the Metro

 

题意:

摘自lrj紫书——

某城市地铁是线性的,有n(2≤n≤50)个车站,从左到右编号1~n。有M1辆列车从第1站开始往右开,还有M2辆列车从第n站开始往左开。列车在相邻站台间所需的运行时间是固定的,因为所有列车的运行速度是相同的。在时刻0,Mario从第1站出发,目的在时刻T(0≤T≤200)会见车站n的一个间谍。在车站等车时容易被抓,所以她决定尽量躲在开动的火车上,让在车站等待的时间尽量短。列车靠站停车时间忽略不计,且Mario身手敏捷,即时两辆方向不同的列车在同一时间靠站,Mario也能完成换乘。

 

思路:

令 bool instationa[i][j] 表示i时刻是否有向左开的列车到达j站台,同理 instationb[i][j] 表示i时刻是否有向右开的列车到达j站台。

f[i][j]表示在i时刻到达j站台所需的最小等待时间,初始化f[i][j]=inf,其中f[0][1]=0。

转移方程:f[i][j]=min{f[i-d[j-1]][j-1] , f[i-d[j]][j+1] , f[i-1][j]+1}

 

注意:

要注意数组上下越界的问题,特别是处理instation时要注意不要处理那些超过数组容量的时间。

 

代码:

#include<bits/stdc++.h>
using namespace std;

#define maxn 50
#define maxt 200
#define inf 1000000
#define sta(a,b) instationa[a][b]
#define stb(a,b) instationb[a][b]

int n,t;
int m1,m2;
int d[maxn+5]= {0},dsum[maxn+5]= {0};
int a[maxn+5]= {0},b[maxn+5]= {0};

bool instationa[maxt+5][maxn+5]= {0};
bool instationb[maxt+5][maxn+5]= {0};
int f[maxt+5][maxn+5]= {0};

void readin() {
	scanf("%d",&t);
	for(int i=1; i<n; i++) scanf("%d",&d[i]);
	scanf("%d",&m1);
	for(int i=1; i<=m1; i++) {
		scanf("%d",&a[i]);
	}
	scanf("%d",&m2);
	for(int i=1; i<=m2; i++) {
		scanf("%d",&b[i]);
	}
}

void init() {
	memset(instationa,0,sizeof(instationa));
	memset(instationb,0,sizeof(instationb));
	memset(dsum,0,sizeof(dsum));
	for(int i=1; i<=n; i++) dsum[i]=dsum[i-1]+d[i-1];

	for(int i=1; i<=m1; i++)
		for(int j=1; j<=n; j++)
			if(a[i]+dsum[j]<=t) instationa[a[i]+dsum[j]][j]=true;
	for(int i=1; i<=m2; i++)
		for(int j=1; j<=n; j++)
			if(dsum[n]-dsum[j]+b[i]<=t) instationb[dsum[n]-dsum[j]+b[i]][j]=true;
			
	for(int i=0; i<=maxt; i++)
		for(int j=0; j<=maxn; j++)
			f[i][j]=inf;
	f[0][1]=0;
	
}

int dp() {
	for(int i=1; i<=t; i++) {
		for(int j=1; j<=n; j++) {
			if(sta(i,j)&&i>=d[j-1]&&j!=1) f[i][j]=min(f[i][j],f[i-d[j-1]][j-1]);
			if(stb(i,j)&&i>=d[j]&&j!=n) f[i][j]=min(f[i][j],f[i-d[j]][j+1]);
			f[i][j]=min(f[i][j],f[i-1][j]+1);
		}
	}
	return f[t][n];
}

int main() {
	int T=0;
	while(~scanf("%d",&n)&&n) {
		readin();
		init();
		int ans=dp();
		printf("Case Number %d: ",++T);
		if(ans<inf) printf("%d\n",ans);
		else printf("impossible\n");
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值