题目描述
Wonderland是小王居住地一家很受欢迎的游乐园。 Wonderland目前有4种售票方式,分别为一日票(1天)、三日票(3天)、周票(7天)和月票(30天)。
每种售票方式的价格将由一个数组给出,每种票据在票面时限内可以无限制的进行游玩。例如,小王在第10日买了一张三日票,小王可以在第10日、第11日和第12日进行无限制的游玩。
小王计划在接下来一年内多次游玩该游乐园。小王计划的游玩日期将由一个数组给出。 现在,请您根据给出的售票价格数组和小王计划游玩日期数组,返回完成游玩计划所需要的最低消费。
输入描述:
输入为2个数组
售票价格数组为costs,costs.length=4,默认顺序为一日票、三日票、周票和月票。
小王计划游玩日期数组为days,1<=days.length<=365,1<=days[i]<=365,默认顺序为升序。
输出描述:
完成游玩计划的最低消费
根据售票价格数组和游玩日期数组给出的信息,发现每次去玩的时候买一张一日票是最省钱的,所以小王会买8张一日票,每张5元,最低花费是40元。
示例1
输入:
5 14 30 100
1 3 15 20 21 200 202 230
输出:
40
解题思路
这个解决方案的步骤如下:
-
输入读取:
- 将每种票的价格(一日票、三日票、周票和月票)读入
pay
数组。 - 将
minpay
设置为票价中的最小值。
- 将每种票的价格(一日票、三日票、周票和月票)读入
-
读取计划游玩日期:
- 读取计划游玩日期直到输入结束,存入
playday
数组。
- 读取计划游玩日期直到输入结束,存入
-
动态规划方法:
- 初始化一个二维数组
dp
,用于存储从第i
天到第j
天的最低消费。dp[i][j]
表示在这个范围内的最低消费。 - 将
dp[i][i]
初始化为minpay
,因为在单日游玩的最低花费就是最低票价。
- 初始化一个二维数组
-
动态规划计算:
- 使用嵌套循环遍历计划游玩日期的所有子区间。
- 计算
dp[j][j+i]
,考虑在j
和j+i
之间的所有可能拆分。 - 通过考虑连续日期之间的最小花费,以及购买1、3、7或30天票是否更经济,更新
dp[j][j+i]
。
-
输出:
- 输出从第0天到第
n-1
天(n
是计划游玩日期的数量)的最低消费。
- 输出从第0天到第
关键思想是使用动态规划计算每个游玩日期子区间的最低消费,考虑不同的票选项。最终结果存储在dp[0][n-1]
中,表示整个计划期间的最低消费。
题解代码
C/C++题解代码
#include <cstdio>
#include <iostream>
using namespace std;
int main() {
int n=0, pay[4], playday[400], dp[400][400];
cin >> pay[0] >> pay[1] >> pay[2] >> pay[3];
int minpay = pay[0];
if(pay[1] < minpay) minpay = pay[1];
if(pay[2] < minpay) minpay = pay[2];
if(pay[3] < minpay) minpay = pay[3];
while (cin >> playday[n]) {
dp[n][n] = minpay;
n++;
}
for(int i=1;i<n;i++)
for(int j=0;j<n-i;j++)
dp[j][j+i] = dp[j][j+i-1] + dp[j+i][j+i];
for(int k=j;k<j+i;k++)
dp[j][j+i] = min(dp[j][j+i], dp[j][k] + dp[k+1][j+i]);
int days = playday[j+i] - playday[j] + 1;
if (days<=3) {
dp[j][j+i] = min(dp[j][j+i], pay[1]);
}
if (days<=7) {
dp[j][j+i] = min(dp[j][j+i], pay[2]);
}
if (days<=30) {
dp[j][j+i] = min(dp[j][j+i], pay[3]);
}
// printf("%d,%d=%d ",j,j+i,dp[j][j+i]);
}
}
}
cout<<dp[0][n-1];
return 0;
}
Python题解代码
def calculate_min_cost(costs, playdays):
n = len(playdays)
minpay = min(costs)
# Initialize a 2D array dp to store the minimum cost
dp = [[0] * n for _ in range(n)]
# Set the diagonal elements to minpay
for i in range(n):
dp[i][i] = minpay
# Dynamic Programming calculation
for i in range(1, n):
for j in range(n - i):
dp[j][j + i] = dp[j][j + i - 1] + dp[j + i][j + i]
for k in range(j, j + i):
dp[j][j + i] = min(dp[j][j + i], dp[j][k] + dp[k + 1][j + i])
days = playdays[j + i] - playdays[j] + 1
if days <= 3:
dp[j][j + i] = min(dp[j][j + i], costs[1])
if days <= 7:
dp[j][j + i] = min(dp[j][j + i], costs[2])
if days <= 30:
dp[j][j + i] = min(dp[j][j + i], costs[3])
return dp[0][n - 1]
# 输入售票价格数组和计划游玩日期数组
costs = list(map(int, input().split()))
playdays = list(map(int, input().split()))
# 计算并输出最低消费
result = calculate_min_cost(costs, playdays)
print(result)
JAVA题解代码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = 0;
int[] pay = new int[4];
int[] playday = new int[400];
int[][] dp = new int[400][400];
for (int i = 0; i < 4; i++) {
pay[i] = scanner.nextInt();
}
int minpay = pay[0];
for (int i = 1; i < 4; i++) {
if (pay[i] < minpay) {
minpay = pay[i];
}
}
while (scanner.hasNextInt()) {
playday[n] = scanner.nextInt();
dp[n][n] = minpay;
n++;
}
for (int i = 1; i < n; i++) {
for (int j = 0; j < n - i; j++) {
dp[j][j + i] = dp[j][j + i - 1] + dp[j + i][j + i];
for (int k = j; k < j + i; k++) {
dp[j][j + i] = Math.min(dp[j][j + i], dp[j][k] + dp[k + 1][j + i]);
}
int days = playday[j + i] - playday[j] + 1;
if (days <= 3) {
dp[j][j + i] = Math.min(dp[j][j + i], pay[1]);
}
if (days <= 7) {
dp[j][j + i] = Math.min(dp[j][j + i], pay[2]);
}
if (days <= 30) {
dp[j][j + i] = Math.min(dp[j][j + i], pay[3]);
}
}
}
System.out.println(dp[0][n - 1]);
}
}
JS题解代码
function calculateMinCost(costs, playdays) {
const n = playdays.length;
const minpay = Math.min(...costs);
// Initialize a 2D array dp to store the minimum cost
const dp = Array.from(Array(n), () => Array(n).fill(0));
// Set the diagonal elements to minpay
for (let i = 0; i < n; i++) {
dp[i][i] = minpay;
}
// Dynamic Programming calculation
for (let i = 1; i < n; i++) {
for (let j = 0; j < n - i; j++) {
dp[j][j + i] = dp[j][j + i - 1] + dp[j + i][j + i];
for (let k = j; k < j + i; k++) {
dp[j][j + i] = Math.min(dp[j][j + i], dp[j][k] + dp[k + 1][j + i]);
}
const days = playdays[j + i] - playdays[j] + 1;
if (days <= 3) {
dp[j][j + i] = Math.min(dp[j][j + i], costs[1]);
}
if (days <= 7) {
dp[j][j + i] = Math.min(dp[j][j + i], costs[2]);
}
if (days <= 30) {
dp[j][j + i] = Math.min(dp[j][j + i], costs[3]);
}
}
}
return dp[0][n - 1];
}
// 示例输入
const costs = [5, 14, 30, 100];
const playdays = [1, 3, 15, 20, 21, 200, 202, 230];
// 计算并输出最低消费
const result = calculateMinCost(costs, playdays);
console.log(result);
代码OJ评判结果
通过测试点
代码讲解
C/C++ 题解代码解析
-
变量和数组定义:
- 使用
int n
记录计划游玩日期的数量。 - 定义数组
pay
存储四种不同类型的票的价格。 - 定义数组
playday
存储计划游玩的日期。 - 定义二维数组
dp
用于动态规划。
- 使用
-
输入:
- 通过
cin
读取四种票的价格到数组pay
。 - 通过循环使用
cin
读取计划游玩的日期到数组playday
。
- 通过
-
计算最低票价:
- 初始化
minpay
为第一种票的价格。 - 遍历四种票的价格,更新
minpay
为最小的票价。
- 初始化
-
动态规划计算最低消费:
- 使用动态规划填充二维数组
dp
。 - 外层循环遍历游玩日期,内层循环进行动态规划计算。
- 在计算过程中,考虑连续日期的最小消费以及购买不同类型票的情况。
- 使用动态规划填充二维数组
-
输出:
- 输出计算得到的最低消费。
Python 题解代码解析
-
函数定义:
- 定义了一个名为
calculate_min_cost
的函数,用于计算最低消费。
- 定义了一个名为
-
变量和数组定义:
- 使用
n
记录计划游玩日期的数量。 - 计算四种票的最低价格,使用
minpay
存储。 - 定义二维数组
dp
用于动态规划。
- 使用
-
动态规划计算最低消费:
- 使用动态规划填充二维数组
dp
。 - 在计算过程中,考虑连续日期的最小消费以及购买不同类型票的情况。
- 使用动态规划填充二维数组
-
输出:
- 输出计算得到的最低消费。
Java 题解代码解析
-
变量和数组定义:
- 使用
Scanner
读取输入。 - 定义数组
pay
存储四种不同类型的票的价格。 - 定义数组
playday
存储计划游玩的日期。 - 定义二维数组
dp
用于动态规划。
- 使用
-
输入:
- 通过
Scanner
读取四种票的价格到数组pay
。 - 通过循环使用
Scanner
读取计划游玩的日期到数组playday
。
- 通过
-
计算最低票价:
- 初始化
minpay
为第一种票的价格。 - 遍历四种票的价格,更新
minpay
为最小的票价。
- 初始化
-
动态规划计算最低消费:
- 使用动态规划填充二维数组
dp
。 - 在计算过程中,考虑连续日期的最小消费以及购买不同类型票的情况。
- 使用动态规划填充二维数组
-
输出:
- 输出计算得到的最低消费。
JavaScript 题解代码解析
-
函数定义:
- 定义了一个名为
calculateMinCost
的函数,用于计算最低消费。
- 定义了一个名为
-
变量和数组定义:
- 使用
n
记录计划游玩日期的数量。 - 计算四种票的最低价格,使用
minpay
存储。 - 定义二维数组
dp
用于动态规划。
- 使用
-
动态规划计算最低消费:
- 使用动态规划填充二维数组
dp
。 - 在计算过程中,考虑连续日期的最小消费以及购买不同类型票的情况。
- 使用动态规划填充二维数组
-
示例输入和计算:
- 提供了示例输入的数组
costs
和playdays
。 - 调用
calculateMinCost
计算最低消费并输出。
- 提供了示例输入的数组
每种语言的代码都实现了相同的逻辑,使用动态规划来计算最低消费。不同之处在于语法和输入输出方式。
寄语
🚀✨ 朋友,希望你的华为OD机试就像是一场轻松的技术party!愿你的代码如同畅快的音符,跳跃在键盘上,最后弹奏出一曲高分之歌。加油,你是技术舞台上的巨星!通过机试,就像是风轻云淡,轻轻松松就把高分收入囊中。祝愿你的编程之旅一路顺风,破风前行,每一行代码都是成功的注脚!🌈💻