游玩费用计算(华为od机考题)

一、题目

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];
    }
}

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值