买橘子
思路
题目很直白:你想买恰好 n 个橘子,商家只卖两种袋装——6 个一袋和 8 个一袋,袋子不能拆开,问最少买几袋?凑不出来就输出 -1。
本质上就是求最小的非负整数解 ,使得
。
怎么做最简单?贪心——优先多用大袋(8个装),因为同样的橘子数,用大袋数量更少。具体来说,从 开始往下试,每次算一下剩余的
能不能被 6 整除,能的话答案就是
,直接输出。如果
一路减到 0 都不行,那就输出 -1。
为什么从大到小枚举 8 的个数就能保证最优?因为 8 > 6,用一个 8 袋替换掉等量的 6 袋,总袋数一定不会增加。所以第一个找到的合法方案就是最优方案。
举个例子:n = 20。先试 ,剩
,4 不能被 6 整除;再试
,剩
,
,答案就是
。
代码
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
int ans = -1;
for (int b = n / 8; b >= 0; b--) {
int rem = n - 8 * b;
if (rem % 6 == 0) {
ans = b + rem / 6;
break;
}
}
cout << ans << endl;
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 ans = -1;
for (int b = n / 8; b >= 0; b--) {
int rem = n - 8 * b;
if (rem % 6 == 0) {
ans = b + rem / 6;
break;
}
}
System.out.println(ans);
}
}
n = int(input())
ans = -1
for b in range(n // 8, -1, -1):
rem = n - 8 * b
if rem % 6 == 0:
ans = b + rem // 6
break
print(ans)
const readline = require('readline');
const rl = readline.createInterface({ input: process.stdin });
const lines = [];
rl.on('line', line => lines.push(line));
rl.on('close', () => {
const n = parseInt(lines[0]);
let ans = -1;
for (let b = Math.floor(n / 8); b >= 0; b--) {
const rem = n - 8 * b;
if (rem % 6 === 0) {
ans = b + rem / 6;
break;
}
}
console.log(ans);
});
复杂度
- 时间复杂度:
,最多循环
次,实际上由于 6 和 8 的最小公倍数是 24,循环最多跑 3 次就能出结果(或者判定无解),可以认为是
。
- 空间复杂度:
,只用了几个变量。



京公网安备 11010502036488号