uva 1025 A Spy in the Metro (DP)

本文介绍了一种求解从起点公交站出发,在特定时间内到达终点公交站的最短时间算法。通过动态规划方法,考虑了车辆双向行驶及乘客换乘情况,实现从任意时刻、任意站点出发的最优路径计算。

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

/*
题意:
    给出车站数N,时刻T,t[i]: i->i+1车站需时间,从1->N方向的m1辆车的发车时间,N->1方向的发车时间,
    求从1->N最短时间。
分析:
    求最短时间,最终状态是T时刻到达N,dp[T][N];
    由于要递推出答案,设dp[i][j]为i时刻,位于车站j到达车站N还需的时间,
    每个状态则有三种转移方向:
    dp[i][j]=dp[i+1][j] 原地等待下一车
            =dp[i+t[j]][j+1] 如果i时刻j站点有向右的车,则搭上向右的车
            =dp[i+t[j-1]][j-1] 如果i时刻j站点有向左的车,则搭上向左的车
    从后向前递推,答案是dp[0][1]
    判断i时刻j站点是否有车还需要预处理一下,用 is_train[i][j][0]记录右向的,is_train[i][j][1]记录左向的。
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <limits.h>
using namespace std;

typedef long long ll;
const int INF=0x3f3f3f3f;
int N,T,m1,m2,t[60],is_train[250][60][2],M1[60],M2[60],dp[250][60];
void read()//读入数据
{
    scanf("%d",&T);
    for(int i=1;i<=N-1;i++)
        scanf("%d",&t[i]);
    scanf("%d",&m1);
    for(int i=1; i<=m1; i++)
        scanf("%d",&M1[i]);
    scanf("%d",&m2);
    for(int i=1; i<=m2; i++)
        scanf("%d",&M2[i]);
}
void pre()//预处理
{
    memset(is_train,0,sizeof(is_train));
    int i,j;
    for(i=1;i<=m1;i++)//对每一辆车
    {
        int temp=M1[i];
        is_train[temp][1][0]=1;
        for(j=1;j<N;j++)//记录这辆车到每个站点的时刻,然后记录
        {
            temp+=t[j];
            if(temp<=T)
                is_train[temp][j+1][0]=1;
            else
                break;
        }
    }
    for(i=1;i<=m2;i++)
    {
        int temp=M2[i];
        is_train[temp][N][1]=1;
        for(j=N-1;j>=1;j--)
        {
            temp+=t[j];
            if(temp<=T)
                is_train[temp][j][1]=1;
            else
                break;
        }
    }
}
void solve()//递归
{
    for(int i=1; i<=N-1; i++)
    {
        dp[T][i]=INF;
    }
    dp[T][N]=0;
    int i,j;
    for(i=T-1; i>=0; i--)
    {
        for(j=1; j<=N; j++)
        {
            dp[i][j]=dp[i+1][j]+1;
            if(j<=N-1&&is_train[i][j][0]&&i+t[j]<=T)
                dp[i][j]=min(dp[i][j],dp[i+t[j]][j+1]);
            if(j>=2&&is_train[i][j][1]&&i+t[j-1]<=T)
                dp[i][j]=min(dp[i][j],dp[i+t[j-1]][j-1]);
        }
    }
}
int main()
{
    //freopen("1025in.txt","r",stdin);
    int casee=1;
    while((scanf("%d",&N)!=EOF)&&N)
    {
        read();//读入数据
        pre();//预处理
        solve();//递归
        if(dp[0][1]>=INF)
            printf("Case Number %d: impossible\n",casee++);
       else
            printf("Case Number %d: %d\n",casee++,dp[0][1]);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值