题目链接

买橘子

题目描述

小明想购买恰好 个橘子。水果商贩只提供每袋 个和每袋 个的包装。小明希望在能买到恰好 个橘子的前提下,购买的总袋数最少。如果无法正好买到 个,则不购买。

解题思路

这是一个典型的线性丢番图方程问题,但由于数据范围很小,我们可以使用更直观的枚举法。

设购买 个装的橘子,和 个装的橘子。我们需要满足以下条件:

  1. ,
  2. 我们希望最小化总袋数

为了让总袋数 最小,我们应该优先使用能装更多橘子的大袋子(即 个装的)。因为用一个 个装的袋子比用一个 个装的袋子能用更少的袋数装更多的橘子。

所以,我们可以采用贪心策略,从多到少地枚举购买 个装的袋数

  • 的最大可能值是
  • 我们让 开始,递减到
  • 对于每一个 的值,我们计算剩下需要购买的橘子数量 rem = n - 8 * i
  • 接着,我们检查 rem 是否能被 整除。
  • 如果 rem 能被 整除(即 rem % 6 == 0),说明我们找到了一个可行的方案。此时, 个装的袋数 就是 rem / 6。因为我们是从最大的 开始枚举的,所以第一个找到的解就是总袋数 最少的解。我们直接输出 即可。

如果循环结束后,我们都没有找到一个可行的方案,那就说明无法恰好凑成 个橘子,此时输出

代码

#include <iostream>

using namespace std;

int main() {
    int n;
    cin >> n;

    int min_bags = -1;

    // 从多到少枚举8个装的袋数
    for (int i = n / 8; i >= 0; --i) {
        int rem = n - 8 * i;
        // 如果剩下的橘子数能被6整除
        if (rem % 6 == 0) {
            int j = rem / 6;
            min_bags = i + j;
            break; // 找到第一个解就是最优解
        }
    }

    cout << min_bags << '\n';

    return 0;
}
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();

        int minBags = -1;

        // 从多到少枚举8个装的袋数
        for (int i = n / 8; i >= 0; i--) {
            int rem = n - 8 * i;
            // 如果剩下的橘子数能被6整除
            if (rem % 6 == 0) {
                int j = rem / 6;
                minBags = i + j;
                break; // 找到第一个解就是最优解
            }
        }
        
        System.out.println(minBags);
    }
}
# 读取橘子总数n
n = int(input())

min_bags = -1

# 从多到少枚举8个装的袋数
for i in range(n // 8, -1, -1):
    rem = n - 8 * i
    # 如果剩下的橘子数能被6整除
    if rem % 6 == 0:
        j = rem // 6
        min_bags = i + j
        break  # 找到第一个解就是最优解

print(min_bags)

算法及复杂度

  • 算法:贪心枚举。
  • 时间复杂度:我们枚举了购买 个装橘子的袋数,循环次数最多为 次。因此,时间复杂度为
  • 空间复杂度:只使用了有限的几个变量,因此空间复杂度为