OJ-0816

题目

在这里插入图片描述

示例1

输入:
5 14 30 100
1 3 15 20 21 200 202 230
输出:	
40

示例2

输入:
5 14 30 100
1 2 3 4 5 6 7 11 12 13
输出:
44

分析

解题思路

这个解决方案的步骤如下:

  1. 输入读取:
    将每种票的价格(一日票、三日票、周票和月票)读入 pay 数组。
    将minpay 设置为票价中的最小值。
  2. 读取计划游玩日期:读取计划游玩日期直到输入结束,存入 playday 数组。
  3. 动态规划方法:
    初始化一个二维数组 dp,用于存储从第i天到第j天的最低消费。
    dp[i][j]表示在这个范围内的最低消费。
    将dp[i][i]初始化为minpay,因为在单日游玩的最低花费就是最低票价。
  4. 动态规划计算:
    使用嵌套循环遍历计划游玩日期的所有子区间。
    计算dp[j][j+i],考虑在j和j+i之间的所有可能拆分。
    通过考虑连续日期之间的最小花费,以及购买1、3、7或30天票是否更经济,更新dp[j][j+i]。
  5. 输出:
    输出从第0天到第 n-1天(n 是计划游玩日期的数量)的最低消费。

关键思想是使用动态规划a计算每个游玩日期子区间的最低消费,考虑不同的票选项。最终结果存储在dp[0] [n-1]中,表示整个计划期间的最低消费。

题解

import java.util.Scanner;

public class Main{
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int[] pay = new int[4];
        for (int i = 0; i < 4; i++) {
            pay[i] = in.nextInt();
        }
        in.nextLine();
        String[] str = in.nextLine().split(" ");
        int n = str.length;
        int[] playDay = new int[n];
        int[][] dp = new int[n][n];
        for (int i = 0; i < n; i++) {
            playDay[i] = Integer.parseInt(str[i]);
            dp[i][i] = pay[0];
        }

        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 < i + j; 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]);
    }
}

参考

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int[] pay = new int[4];
        for (int i = 0; i < 4; i++) {
            pay[i] = in.nextInt();
        }
        in.nextLine();
        String[] str = in.nextLine().split(" ");
        int n = str.length;
        int[] playDay = new int[n];
        int[][] dp = new int[400][400];
        for (int i = 0; i < str.length; i++) {
            playDay[i] = Integer.parseInt(str[i]);
            dp[i][i] = pay[0];
        }

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

https://blog.csdn.net/weixin_52908342/article/details/135338098

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值