一、题目
1.原题
Wonderland是小王居住地一家很受欢迎的游乐园。
Wonderland目前有4种售票方式,
分别为一日票(1天)、三日票(3天)、周票(7天)和月票(30天)。
每种售票方式的价格将由一个数组给出,
每种票据在票面时限内可以无限制的进行游玩。
例如,小王在第10日买了一张三日票,小王可以在第10日、第11日和第12日进行无限制的游玩。
小王计划在接下来一年内多次游玩该游乐园。
小王计划的游玩日期将由一个数组给出。
现在,请您根据给出的售票价格数组和小王计划游玩日期数组,
返回完成游玩计划所需要的最低消费。
2.题目理解
售票方式:ticket:[1,3,7,30]
售票方式的价格:price:[88,258,588,1888]
(不考虑月份,0-365天)
游玩日期数组:plan[2,3,6,10,19,20,30,97]
二、思路与代码过程
1.思路
动态规划。
创建int[] dp = new int[366](从1开始),dp[i]表示到第i天一共花的金额。
eg:0,1天都不去,从第二天开始去,当前计费最小方式就是单日票dp[2]=88,如果选三日票dp[2]=258;第三天也去,dp[3]=dp[2]+88/258(dp[3-3]+258=0+258)选择小的那个,dp[3]=88*2;
当当前天数小于套餐天数时(6<7<30,按照dp[0]+price[2]/+price[3])。
2.代码过程
①main函数
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int ticket[] = {1,3,7,30};
System.out.println("请输入票价数组:");
int price[] = new int[ticket.length];
for (int i = 0; i < price.length; i++) {
price[i] = sc.nextInt();
}
System.out.println("请输入游玩天数:");
int days = sc.nextInt();
System.out.println("请输入游玩日期数组:");
int plan[] = new int[days];
for (int i = 0; i < plan.length; i++) {
plan[i] = sc.nextInt();
}
int expenditure = LowestCostCal(ticket,price,plan);
System.out.println("完成该游玩计划需要的最低消费为:"+expenditure);
}
②LowestCostCal
private static int LowestCostCal(int[] ticket, int[] price, int[] plan) {
int dp[] = new int[366];
boolean travel[] = new boolean[366];
for (int day :plan){
travel[day] = true;
}
for (int i = 1; i <= 365; i++) {
if (!travel[i]) {
dp[i] = dp[i-1];//不去游玩则与前天一致
continue;
}
/*dp[Math.max(0,i-1)]+price[0]:
表示第i天的消费=前一天i-1的消费dp[i-1]加上如果选择一日票的消费,
其中Math.max(0,i-1)避免数组越界 */
dp[i] = dp[i-1] + price[0];//单日票消费
/*向前涵盖最小*/
dp[i] = Math.min(dp[i],dp[Math.max(0,i-ticket[0])]+price[0] );
//比较一日票
dp[i] = Math.min(dp[i],dp[Math.max(0,i-ticket[1])]+price[1] );
//比较三日票,dp[i]=今天单日票加之前价格和三天前价格加三天票价格之中较小的
dp[i] = Math.min(dp[i],dp[Math.max(0,i-ticket[2])]+price[2] );
//比较七日票
dp[i] = Math.min(dp[i],dp[Math.max(0,i-ticket[3])]+price[3] );
//比较月票
}
return dp[366];
}
三、运行结果
1.运行截图
2.完整代码
import java.util.Arrays;
import java.util.Scanner;
public class test37 {
public static void main(String[] args) {
///*
Scanner sc = new Scanner(System.in);
int ticket[] = {1,3,7,30};
System.out.println("请输入票价数组:");
int price[] = new int[ticket.length];
for (int i = 0; i < price.length; i++) {
price[i] = sc.nextInt();
}
//System.out.println(Arrays.toString(price));
System.out.println("请输入游玩天数:");
int days = sc.nextInt();
System.out.println("请输入游玩日期数组:");
int plan[] = new int[days];
for (int i = 0; i < plan.length; i++) {
plan[i] = sc.nextInt();
}
//System.out.println(Arrays.toString(plan));
//*/
//int ticket[] = {1,3,7,30};
//int price[] = {88,258,588,1888};
//int plan[] = {2,3,6,10,19,20,30,97};
//
//int plan[] = {2,3,4,10,11,12,13,15,16,50,55,56,57,59,60,61,66,68};
int expenditure = LowestCostCal(ticket,price,plan);
System.out.println("完成该游玩计划需要的最低消费为:"+expenditure);
}
private static int LowestCostCal(int[] ticket, int[] price, int[] plan) {
int dp[] = new int[366];
boolean travel[] = new boolean[366];
for (int day :plan){
travel[day] = true;
}
for (int i = 1; i <= 365; i++) {
if (!travel[i]) {
dp[i] = dp[i-1];//不去游玩则与前天一致
continue;
}
/*dp[Math.max(0,i-1)]+price[0]:
表示第i天的消费=前一天i-1的消费dp[i-1]加上如果选择一日票的消费,
其中Math.max(0,i-1)避免数组越界 */
dp[i] = dp[i-1] + price[0];//单日票消费
/*向前涵盖最小*/
dp[i] = Math.min(dp[i],dp[Math.max(0,i-ticket[0])]+price[0] );//比较一日票
dp[i] = Math.min(dp[i],dp[Math.max(0,i-ticket[1])]+price[1] );//比较三日票,dp[i]=今天单日票加之前价格和三天前价格加三天票价格之中较小的
dp[i] = Math.min(dp[i],dp[Math.max(0,i-ticket[2])]+price[2] );//比较七日票
dp[i] = Math.min(dp[i],dp[Math.max(0,i-ticket[3])]+price[3] );//比较月票
}
return dp[365];
}
}