在接下来的一年里,你要旅行的日子将以一个名为
每一项是一个从
火车票有三种不同的销售方式 :
- 一张为期一天的通行证售价为
- 一张为期七天的通行证售价为
- 一张为期三十天的通行证售价为
通行证允许数天无限制的旅行。
例如,如果我们在第
返回你想要完成在给定的列表
第一行输入一个整数,表示
数组的长度。
第二行输入个数,表示
的数组的值。
第三行输入三个数表示数组。
。
。
按顺序严格递增。
。
。
输出旅行所需要的最低消费
6 1 4 6 7 8 20 2 7 15
11
/******************************************************************************
* 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;
}