【Codeforces】1625C Road Optimization 题解

题目大意

两个城市相聚 l l l千米,要从起点城市通过一条路到达目标城市,路上有 n n n个限速点(第一个限速点在起点),每个限速点位置在 d i d_i di,值为 b i b_i bi,表示从这个限速点到下个限速点位置,每经过一千米需要花费 b i b_i bi点单位时间。

你可以删掉不超过 k k k个限速点,请问删除后到达目标城市的最短时间是多少?

思路

A A A限速点到达 B B B限速点所需时间与怎么到 A A A没有关系,只于还有多少删除机会有关。

进一步讲,到达 A A A点肯定是从 A A A点前某一个点来的,到达 A A A点之后,就和它没关系了,所以我们想到了动态规划来解决这个问题。

d p [ i ] [ j ] dp[i][j] dp[i][j]表示从起点到达 i i i号限速点,并用掉了 j j j次删除机会,所能达到的最短时间。

我们从这个点往后走,那么有 d p [ i + c n t ] [ j + c n t − 1 ] = m i n ( d p [ i + c n t ] [ j + c n t − 1 ] , d p [ i ] [ j ] + ( d [ i + c n t ] − d [ i ] ) ∗ b [ i ] ) , 其 中 j + c n t − 1 ≤ k dp[i+cnt][j+cnt-1] = min(dp[i+cnt][j+cnt-1], dp[i][j] + (d[i+cnt]-d[i]) * b[i]),其中j+cnt-1 \le k dp[i+cnt][j+cnt1]=min(dp[i+cnt][j+cnt1],dp[i][j]+(d[i+cnt]d[i])b[i]),j+cnt1k

代码

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;

const int maxN = 505, INF = 0x3f3f3f3f;

int dp[maxN][maxN], n, l, k, b[maxN], d[maxN];

int main()
{
    scanf("%d%d%d", &n, &l, &k);
    for(int i = 0; i < n; ++i)
        scanf("%d", &d[i]);
    for(int i = 0; i < n; ++i)
        scanf("%d", &b[i]);
    memset(dp, 0x3f, sizeof dp);
    dp[0][0] = 0; d[n] = l;
    for(int i = 1; i <= n; ++i)
        dp[i][0] = dp[i - 1][0] + b[i - 1] * (d[i] - d[i - 1]);
    for(int i = 0; i < n; ++i)
        for(int j = 0; j <= k; ++j) 
            for(int pos = i + 1; pos <= n; ++pos)
                dp[pos][j + pos - i - 1] = min(dp[pos][j + pos - i - 1], dp[i][j] + b[i] * (d[pos] - d[i]));
    int ans = INF;
    for(int i = 0; i <= k; ++i)
        ans = min(ans, dp[n][i]);
    printf("%d\n", ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值