题意: 某城市的地铁是线性的,有n(2≤n≤50)个车站,从左到右的编号为1~N.有M1辆列车从第一站开始往右开,还有M2辆列车从第n站开始往左开。在时刻0,Mario从第1站出发,目的是在时刻T(0≤T≤200)会见车站n的一个间谍。在车站等车容易被抓,所以她决定尽量躲在开动的火车上,让在车站等待的总时间尽量短。列车靠站停车时间忽略不计,且Mario身手敏捷,即使两辆方向不同的列车在同一时间靠站,Mario也能完成换乘。求最少等待时间
思路: 这是一道给出 固定终点的求最最短等待时间的题,1,首先时间是单向流逝的,是一个天然的序,2.可以把时间t,站 n,看做一个点,建图,下面代码中has[i][j][0] 是代表当时间为i,站为j时,看看是否有向右的车,has[][][1] 是看看是否有向左的车;3 因时间是一个天然的序,dp[i][j] 代表 当时间为i,站为j 时,要到达 时间为t,站为n,需要等待的最短时间;则采用逆推法,dp[t][n] 一定为0吧,逆推法一只到dp[0][1];(在刘汝佳老师的紫书上,讲的DAG 上的动态规划上 的 硬币问题也可以采用逆推法,把终点设为s,我的收藏中有终点为0的)
在这个状态转移的过程中,无非有三种决策
1 没有车,等上一分钟,看看下一分钟有没有车;
2 若有向右的车,搭载向右的车;
3 若有向左的车,搭载向左的车;
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define Max 210
#define INF 0x3f3f3f3f
int time[60],has[Max][60][2];
int dp[Max][60]; // dp[i][j] 时间为i分,j站,到达时间t,n站的需要等的最小时间;
int n,t,M1,M2;
void init()
{
memset(has,0,sizeof(has));
memset(dp,INF,sizeof(dp));
}
int main()
{
int i,j,k,num=1;
while(~scanf("%d",&n)&&n)
{
init();
scanf("%d",&t);
for(i=1;i<n;i++)
scanf("%d",&time[i]);
scanf("%d",&M1);
for(i=1; i<=M1; i++) //建图,时间t,站n,为一个坐标(t,n),has 数组是看看有没有开往相邻坐标的车,相邻坐标由站和站于站之间的时间决定;
{ //has[i][j][0] ,表示看看有没有开往右边的车,has[i][j][1],看看有没有开往左边的车;
scanf("%d",&k);
for(j=1;j<=n;j++)
{
if(j==1) has[k][j][0] = 1;
else
{
k = k + time[j-1];
if(k>t) continue;
has[k][j][0] = 1;
}
}
}
scanf("%d",&M2);
for(i = 1; i <= M2; i ++)
{
scanf("%d",&k);
for(j = n;j >=1;j --)
{
if(j==n) has[k][j][1] = 1;
else
{
k = k + time[j];
if(k>t) continue;
has[k][j][1] = 1;
}
}
}
dp[t][n] = 0; // 逆推法,因为当时间为t,n站,到达时间为t,n站,需要的最小时间一定是0;
// 随的时间减少,那么到时间t,n站的需要等的时间,会增加,也可能不变;
//状态转移;
for(i = t - 1; i >= 0; i--)
{
for(j = 1 ; j <= n; j++)
{
dp[i][j] = dp[i+1][j] + 1; //等一分钟;如果等一分钟,就到了i+1分钟,j站,从i+1分钟,j站这个状态,
if(j<n&&has[i][j][0]&&i+time[j]<=t) //需要看i+1分,j站时,需要等车时间,在这个时间上再加1,就是dp[i][j],等一分钟的时间;
{
dp[i][j] = min(dp[i][j],dp[i+time[j]][j+1]); // 坐车时间不算,dp 数组中存的时间为在每一站等车的时间;
}
if(j>1&&has[i][j][1]&&i+time[j-1]<=t)
{
dp[i][j] = min(dp[i][j],dp[i+time[j-1]][j-1]);
}
}
}
if(dp[0][1]>=INF)
printf("Case Number %d: impossible\n",num++);
else printf("Case Number %d: %d\n",num++,dp[0][1]);
}
return 0;
}
本文介绍了一种解决特定场景下最短等待时间问题的动态规划算法,通过构建时间与站点坐标图,利用逆推法求解从起点到终点的最小等待时间。
2733

被折叠的 条评论
为什么被折叠?



