首页 > 试题广场 >

最低票价

[编程题]最低票价
  • 热度指数:163 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
在一个火车旅行很受欢迎的国度,你提前一年计划了一些火车旅行。
在接下来的一年里,你要旅行的日子将以一个名为 days 的数组给出。
每一项是一个从 1365 的整数。
火车票有三种不同的销售方式 :
- 一张为期一天的通行证售价为 costs[0] 美元;
- 一张为期七天的通行证售价为 costs[1] 美元;
- 一张为期三十天的通行证售价为 costs[2] 美元。
通行证允许数天无限制的旅行。
例如,如果我们在第 2 天获得一张为期 7 天的通行证,那么我们可以连着旅行 7 天:第 2 天、第 3 天、第 4 天、第 5 天、第 6 天、第 7 天和第 8 天。
返回你想要完成在给定的列表 days 中列出的每一天的旅行所需要的最低消费 。

输入描述:
第一行输入一个整数 n,表示 days 数组的长度。
第二行输入 n 个数,表示 days 的数组的值。
第三行输入三个数表示 cost 数组。
1 <= days.length <= 365
1 <= days[i] <= 365
days 按顺序严格递增。
costs.length == 3
1 <= costs[i] <= 1000


输出描述:
输出旅行所需要的最低消费
示例1

输入

6
1 4 6 7 8 20
2 7 15

输出

11
题目可能有误:
1. 数据没有满足“days按顺序严格递增”
2. 有数据的预期输出(2002)和我手算的结果(1848)不同

以下是我的实现代码,如有问题,欢迎大家指出
/******************************************************************************
 * algo > DP
 *      > 约定 days[] 1-index, costs[] 0-index
 *      > (以下的 i 等序号默认指 days[i], 即第 i 个给出的日期)
 *        f[i]: 完成 days[1..i] 的旅行所需要的最低消费
 *        f[i] = min{f[p[i][0]] + costs[0],
 *                   f[p[i][1]] + costs[1],
 *                   f[p[i][2]] + costs[2]}, i >= 1
 *            p[i][0] 是从第 i 个日期往前数, 到哪个日期恰好超过 1 天
 *            p[i][1], p[i][2] 同理, 对应 7 天, 30 天的通行证
 *        f[0] = 0
 *      > p[i][.] 可以通过双指针计算
 * note > 该算法应该在 days 有重复时也正确
 *****************************************************************************/
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <cstring>

using namespace std;

const int kMaxN = 365;
const int kCostsLen = 3;
const int kPermitLen[] = {1, 7, 30};
const int kInf = 0x3fffffff;

int days[kMaxN+5];
int costs[kCostsLen];

int f[kMaxN+5];
int p[kMaxN+5][kCostsLen];

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(0);

	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> days[i];
	// 保证 days[i] 递增
	sort(days+1, days+n+1);
	for (int i = 0; i < kCostsLen; i++)
		cin >> costs[i];

	// 计算 p[][]
	for (int j = 0; j < kCostsLen; j++) {
		int l = 0;
		for (int i = 1; i <= n; i++) {
			while (days[i]-days[l+1]+1 > kPermitLen[j])
				l++;
			p[i][j] = l;
		}
	}

	// DP
	f[0] = 0;
	for (int i = 1; i <= n; i++) {
		f[i] = kInf;
		for (int j = 0; j < kCostsLen; j++) {
			f[i] = min(f[i], f[p[i][j]] + costs[j]);
		}
	}
	cout << f[n] << '\n';

	return 0;
}


发表于 2025-12-26 15:34:14 回复(3)