第十七届同济大学程序设计预选赛暨高校网络友谊赛 C-张老师的旅行

链接:https://ac.nowcoder.com/acm/contest/5477/C
来源:牛客网

题目描述

张老师到了一个王国去旅游,王国有n个景点,张老师到达这个城市所在的车站恰好位于第x个景点,这个王国非常特别,恰好所有著名的景点都在分布在直线上,每个景点在坐标pi上(单位:公里),张老师身体非常好,每走一公里花费一分钟。每个景点都有一个打卡点,并且必须在不迟于相应的时间(时间从张老师到达王国开始计算)前到达才能打卡成功并且给以一个打卡标记,集齐所这些标记就能获得一个大礼包。由于张老师非常想要大礼包,并且因为张老师还着急去下一个王国旅游,所以张老师希望用的时间尽量少,你能帮帮张老师吗?

输入描述:

输入的第一行,包含一个整数n(1≤n≤1000)。
第二行包含n个整数pi(1≤pi≤100000),第i个整数pi为第i个景点的坐标(坐标从小到大排列)。
最后一行包含n个整数ti(0≤ti≤10,000,000),ti表示第i个景点最迟到达的时间,时间为0则表示张老师所在车站的位置且只有一个为0。

输出描述:

输出所需的最少时间,若无解输出-1。

示例1

输入

[复制](javascript:void(0)😉

4
1 2 3 4
0 1 2 3

输出

[复制](javascript:void(0)😉

3

思路:

这是一个区间DP的问题,

\(dp_R[i][j]\)代表打卡完了第\([i,j]\)所有景点后在最右端(第\(\mathit j\)个景点)时花费的最小时间。

\(dp_L[i][j]\)代表打卡完了第\([i,j]\)所有景点后在最左端(第\(\mathit i\)个景点)时花费的最小时间。

初始状态:

\(pos\)=张老师最初所在车站的位置

\(dp_R[pos][pos]=dp_L[pos][pos]=0\)

状态转移:

\(dp_R[i][j]\)分别可以从\(dp_R[i][j-1],dp_L[i][j-1]\)两个状态转移过来。

\(dp_L[i][j]\)分别可以从\(dp_R[i+1][j],dp_L[i+1][j]\)两个状态转移过来。

转移是判断下最短耗时是否小于等于对应景点的限制时间。

代码:

const int maxn = 1010;
const int inf = 0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
#define DEBUG_Switch 0
int n;
int p[maxn];
int dp_L[maxn][maxn];
int dp_R[maxn][maxn];
int t[maxn];
int main()
{
#if DEBUG_Switch
    freopen("C:\\code\\input.txt", "r", stdin);
#endif
    //freopen("C:\\code\\output.txt","r",stdin);
    n = readint();
    repd(i, 1, n)
    {
        p[i] = readint();
    }
    repd(i, 1, n) {
        repd(j, 1, n)
        {
            dp_R[i][j] = inf;
            dp_L[i][j] = inf;
        }
    }
    repd(i, 1, n)
    {
        t[i] = readint();
        if (t[i] == 0)
        {
            dp_L[i][i] = 0;
            dp_R[i][i] = 0;
        }
    }
    repd(len, 2, n)
    {
        for (int i = 1; i <= n - len + 1; ++i)
        {
            int j = i + len - 1;
            int temp;
            temp = dp_R[i][j - 1] + abs(p[j - 1] - p[j]);
            if (temp <= t[j])
            {
                dp_R[i][j] = min(temp, dp_R[i][j]);
            }
            temp = dp_L[i][j - 1] + abs(p[i] - p[j]);
            if (temp <= t[j])
            {
                dp_R[i][j] = min(temp, dp_R[i][j]);
            }
            temp = dp_R[i + 1][j] + abs(p[j] - p[i]);
            if (temp <= t[i])
            {
                dp_L[i][j] = min(temp, dp_L[i][j]);
            }
            temp = dp_L[i + 1][j] + abs(p[i + 1] - p[i]);
            if (temp <= t[i])
            {
                dp_L[i][j] = min(temp, dp_L[i][j]);
            }
        }
    }
    int ans = min(dp_R[1][n], dp_L[1][n]);
    if (ans == inf)
        ans = -1;
    printf("%d\n", ans );
    return 0;
}