Loading

VIJOS-P1421 更换轮胎

题目传送门

描述

经过数周的期待,比赛终于正式开始。

不过天公不作美,今天的天气十分诡异,一会儿下雨,一会儿刮风。要知道,天气的变化对F1比赛的影响是巨大的,恶劣的天气甚至会严重干扰赛车手发挥。因此,各车队的总指挥都会在赛前根据赛道环境和天气的变化为车手制定一系列周密的计划。

幸运的是,F1专用气象站拥有最顶尖的技术,能够精确测量出每一圈的天气情况,这大大降低了计划的风险。

在计划中,对轮胎的正确选择是至关重要的。每一场比赛,赛会都会提供给各赛车不同总类的轮胎(每种轮胎数量不限)。

出发时,各赛车可根据需要使用任意一种轮胎。以后每过一圈,赛车可以选择不更换轮胎继续前进,或者进维修站更换任一种轮胎,但需要消耗一定的换胎时间。

通过测试,换胎时间和各种轮胎在各圈所消耗的单圈时间已精确测出,你能帮车队求出完成比赛的最短时间么?

格式

输入格式

第一行是三个整数\(n,~m,~c~(1 \le n,m \le 1,000,~1 \le c \le 1,000,000)\),分别表示总圈数,轮胎种类数和换胎时间。接下来 \(n\) 行,每行 \(m\) 个整数,第 \(i\) 行第 \(j\) 个是 \(t[i][j] ~ (1 \le t[i][j] \le 1,000,000)\),表示在第 \(i\) 圈时第 \(j\) 种轮胎所消耗的单圈时间。

输出格式

一个整数 \(s\),表示最短的总时间。

样例

样例输入

4 3 30
50 60 100
70 50 100
10 50 90
100 30 10

样例输出

170

限制

各个测试点 \(1s\)

提示

\(30\%\) 的数据满足 \(n \le 15,~m \le 2\)


题解

简单的 \(DP\)\(dp[i][j]\) 表示第 \(i\) 圈选择第 \(j\) 种轮胎所耗的最短时间。

\(mn\) 为上一轮 \(DP\) 中的最小值,即 \(mn = \min \lbrace dp[i-1][1],~dp[i-1][2],~\dots~,~dp[i-1][m] \rbrace\)

则状态转移方程为 \(dp[i][j] = \min(dp[i-1][j],~mn+c)+t[i][j]\)

代码如下:

#include <cstdio>
#include <algorithm>
 
using namespace std;
 
#define N 1010
 
int n, m, c, t[N][N], dp[N][N], mn, ans = 1<<30;

int main()
{
    scanf("%d%d%d", &n, &m, &c);
    for(int i = 1; i <= n; i++) for(int j = 1; j <= m; j++) scanf("%d", &t[i][j]);
    for(int i = 1; i <= m; i++) dp[1][i] = t[1][i];
    for(int i = 2; i <= n; i++)
    {
        mn = 1<<30;
        for(int j = 1; j <= m; j++)
            mn = min(mn, dp[i-1][j]);
        for(int j = 1; j <= m; j++)
            dp[i][j] = min(dp[i-1][j], mn+c) + t[i][j];
    }
    for(int i = 1; i <= m; i++) ans = min(ans, dp[n][i]);
    printf("%d", ans);
    return 0;
}

从代码中我们可以发现:空间复杂度为 \(O(n^2)\)。那么此时我们再考虑能否优化空间复杂度。

不难发现 \(dp[i][j]\) 的更新只与 \(dp[i-1][j]\) 以及 \(mn\) 有关,完全可以将 \(dp\) 数组由二维降维打击成一维的:

#include <cstdio>
#include <algorithm>

#define N 1010

using namespace std;

int n, m, c, dp[N], t[N][N], mn = 1<<30, ans = 1<<30;

int main()
{
    scanf("%d%d%d", &n, &m, &c);
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= m; j++)
            scanf("%d", &t[i][j]);
    for(int i = 1; i <= m; i++) dp[i] = t[1][i];
    for(int i = 2; i <= n; i++, mn = 1<<30)
    {
        for(int j = 1; j <= m; j++)
            mn = min(mn, dp[j]);
        for(int j = 1; j <= m; j++)
            dp[j] = min(dp[j], mn+c) + t[i][j];
    }
    for(int i = 1; i <= m; i++)
        ans = min(ans, dp[i]);
    printf("%d", ans);
    return 0;
}

最后,优化后的 \(DP\)\(O(n)\) 这样一个优秀的空间复杂度解决了此题。

posted @ 2021-06-03 14:01  Chy12321  阅读(64)  评论(0编辑  收藏  举报