UVA 1025 - A Spy in the Metro(动态规划)

本文解析了一道经典的动态规划算法题目,涉及列车调度问题。通过三维数组记录站点、时间和方向上的列车信息,从终点出发逆向求解,实现对列车运行路径的最优化选择。

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

算法竞赛入门经典 第二版 的第一个动规例题。 在思考了好久之后 终于写完 还是按照书中代码写的。 


现在脑子里还想不出完整的模型,  


对这个题的理解, 就是在某一个状态下, 都有好几个状态可以让自己选择去走, 然后每一个都去试试, 最终维护最小值


这个题是有 n个车站,从左边都有每隔一段时间 会有一次发车, 右边也是, 这个人必须在指定的时间 指定的地点 到达某处, 


所以会有了 下车 , 左走 等待 右走的情况。


用 have_train【a】【b】【c】 三维来描述某一个站点  某一时刻 是否有车  有的话 是向哪走,


因为终点的状态很确定 必然是 dp【time】【n】 即 在 time 时间的时候正好达到n站点


我们可以 从 终点的状态 往起始的状态转化, 一步步走就可以了。


#include <cstdio>
#include <algorithm>
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <set>
#include <cmath>
#include <stack>
#include <queue>
#include <cstring>
#define ll long long;
#define maxn 300 + 10
#define INF 10000000
using namespace std;
int main(){
    int n,counts = 0;
    while(scanf("%d",&n) && n){
        int ti;
        int go[maxn];
        int have_train[maxn][maxn][2];
        memset(have_train,0,sizeof(have_train));
        scanf("%d",&ti);
        for(int i = 1 ; i < n ; i ++)
        scanf("%d",&go[i]);
        int num1;
        scanf("%d",&num1);
        for(int i = 0 ; i < num1 ; i++){
            int start ;
            scanf("%d",&start);
            have_train[start][1][0] = 1;
            for(int j = 1 ; j < n; j ++){
             if(go[j] + start <= ti)
              have_train[go[j] + start][j + 1][0] = 1;
              start += go[j];
            }
        }
        int num2;
        scanf("%d",&num2);
        for(int i = 0 ; i < num2 ; i++){
            int start ;
            scanf("%d",&start);
            have_train[start][n][1] = 1;
            for(int j = n; j > 1 ; j --)
            if(go[j - 1] + start <= ti){
             have_train[go[j - 1] + start][j - 1][1] = 1;
             start += go[j - 1];
            }
        }
        int dp[maxn][maxn];
        for(int i = 1 ; i < n ; i++) dp[ti][i] = INF;
        dp[ti][n] = 0;
        for(int i = ti - 1; i >= 0 ; i --){
            for(int j = 1 ; j <= n ; j++){
                dp[i][j] = dp[i + 1][j] + 1;
                if(j < n && i + go[j] <= ti && have_train[i][j][0]){
                    dp[i][j] = min(dp[i][j],dp[i + go[j]][j + 1]);
                }
                if(j > 1 && i + go[j - 1] <= ti && have_train[i][j][1]){
                    dp[i][j] = min(dp[i][j],dp[i + go[j - 1]][j - 1]);
                }
            }
        }
        if(dp[0][1] >= INF)
        printf("Case Number %d: impossible\n",++counts);
        else
        printf("Case Number %d: %d\n",++counts,dp[0][1]);
    }
    return 0;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值