返回 课程

信奥AC之路-2级

0% 完成
0/0 步骤
  1. 第一课:字符
    5 主题|小节
  2. 第二课 嵌套循环与矩形图案(一)
    4 主题|小节
  3. 第三课 嵌套循环与矩形图案(二)
    3 主题|小节
  4. 第四课:矩形三
    5 主题|小节
  5. 第五课:字符矩形
    7 主题|小节
  6. 第六课:直角三角形
    6 主题|小节
  7. 第七课:倒三角形
    7 主题|小节
  8. 第八课:字符三角形
    8 主题|小节
  9. 第九课:字符倒三角形
    7 主题|小节
  10. 第十课:平行四边形
    6 主题|小节
  11. 第十一课:字符直角三角形
    5 主题|小节
  12. 第十二课:左斜三角形
    6 主题|小节
  13. 第十三课:等腰三角形
    6 主题|小节
  14. 第十四课:倒置等腰三角形
    7 主题|小节
  15. 第十五课:上下对称图形
    4 主题|小节
  16. 第十六课:复杂对称图形
    5 主题|小节
  17. 第十七课:左右对称图形
    5 主题|小节
  18. 第十八课:空心图形
    5 主题|小节
  19. 第十九课:空心图形
    3 主题|小节
  20. 第二十课:嵌套应用
    4 主题|小节
  21. 第二十一课:嵌套应用二
    4 主题|小节
  22. 第二十二课:嵌套应用三
    3 主题|小节
  23. 第二十三课:嵌套应用四
    3 主题|小节
课 23, 主题|小节 1
进行中

23.1 购买决策问题

2026年1月16日
课 进展
0% 完成

“购买决策问题是我们生活中常见的数学问题,”我微笑着解释道,”当我们有一定的预算,想要购买不同种类的物品,并且需要满足一些特定条件时,就需要通过计算找出所有可能的方案。”

23.1.1 买小猫小狗

题目描述:某动物饲养中心用X元专款购买小狗(每只A元)和小猫(每只B元)两种小动物。要求专款专用,至少猫狗各一只,正好用完。请求出方案的总数。如没有方案请输出0。

输入: 输入一行,只有三个整数,分别为X, A, B。(100 < X < 32768,1 ≤ A ≤ 100,1 ≤ B ≤ 100)

输出: 输出只有一行,包括1个整数,表示可行方案的总数。

样例输入

1700 31 21

样例输出

3

代码实现(方法一:双重循环)

#include <iostream>
using namespace std;

int main() {
    int x, a, b;
    cin >> x >> a >> b;         // 读取总资金x、小狗单价a、小猫单价b
    int cnt = 0;                // 初始化方案计数器
    
    for(int i = 1; i <= (x - b) / a; i++) {  // i是小狗的数量,至少买1只,最多买(x-b)/a只(预留至少买1只小猫)
        for(int j = 1; j <= (x - a) / b; j++) {  // j是小猫的数量,至少买1只,最多买(x-a)/b只(预留至少买1只小狗)
            if(i * a + j * b == x) {         // 判断当前组合是否刚好花完所有钱
                // cout << i << " " << j << endl;  // 输出具体方案(用于调试)
                cnt++;                        // 累加有效方案数
            }
        }
    }
    
    cout << cnt;                // 输出方案总数
    return 0;
}

代码实现(方法二:优化循环)

#include <iostream>
using namespace std;

int main() {
    int x, a, b;
    cin >> x >> a >> b;         // 读取总资金x、小狗单价a、小猫单价b
    int cnt = 0;                // 初始化方案计数器
    
    for(int i = 1; i <= (x - b) / a; i++) {  // i是小狗的数量,至少买1只,最多买(x-b)/a只
        int s = x - i * a;      // 计算买完i只小狗后剩余的钱
        if(s % b == 0 && s / b >= 1) {  // 判断剩余的钱是否能整除小猫单价,且至少能买1只小猫
            // cout << i << " " << s / b << endl;  // 输出具体方案(用于调试)
            cnt++;              // 累加有效方案数
        }
    }
    
    cout << cnt;                // 输出方案总数
    return 0;
}

思考

  • 方法一使用双重循环,外循环遍历小狗的可能数量,内循环遍历小猫的可能数量
  • 方法二优化了内循环,直接计算剩余金额能购买的小猫数量
  • 方法二的时间复杂度为O(n),而方法一的时间复杂度为O(n²)
  • 注意循环的边界条件:至少猫狗各一只,且总金额刚好用完

23.1.2 恐龙园买玩具

题目描述:小明暑假来到恐龙园游玩,在恐龙园的礼物店里,有一些形形色色的小恐龙玩偶,小明想购买其中霸王龙和三角龙玩偶送给自己的5位好朋友。店员告诉小明,霸王龙玩偶一只需要x元,三角龙玩偶一只需要y元。小明有n元,希望两种恐龙都能购买,购买的霸王龙的数量≥三角龙的数量,购买的总数要在5个或者5个以上(这样才够分),而且不能有钱剩下。请你编程帮助小明输出所有可能的购买方案。

输入: 三个整数n x y,分别代表总金额、霸王龙的单价、三角龙的单价。

输出: 所有满足条件的购买方案,每组购买方案占1行,用空格隔开2个数分别代表霸王龙的数量和三角龙的数量。按霸王龙的数量从少到多,三角龙的数量从多到少的顺序输出。

样例输入

100 10 5

样例输出

7 6
8 4
9 2

代码实现(方法一:双重循环)

#include <iostream>
using namespace std;

int main() {
    int n, x, y;
    cin >> n >> x >> y;         // 读取总金额n、霸王龙单价x、三角龙单价y
    
    for(int i = 1; i <= (n - y) / x; i++) {  // i是霸王龙的数量,从1开始,最多购买(n-y)/x只(预留至少一只三角龙)
        for(int j = 1; j <= (n - x) / y; j++) {  // j是三角龙的数量,从1开始,最多购买(n-x)/y只(预留至少一只霸王龙)
            if(i + j >= 5 && i >= j && i * x + j * y == n) {  // 判断:总数≥5,霸王龙数量≥三角龙数量,且刚好花完钱
                cout << i << " " << j << endl;  // 输出满足条件的方案
            }
        }
    }
    
    return 0;
}

代码实现(方法二:优化循环)

#include <iostream>
using namespace std;

int main() {
    int n, x, y;
    cin >> n >> x >> y;         // 读取总金额n、霸王龙单价x、三角龙单价y
    
    for(int i = 1; i <= (n - y) / x; i++) {  // i是霸王龙的数量,从1开始,最多购买(n-y)/x只
        int s = n - i * x;      // 计算买完i只霸王龙后剩余的钱
        if(s % y == 0 && i >= s / y && i + s / y >= 5) {  // 判断:剩余钱能整除三角龙单价,霸王龙数量≥三角龙数量,且总数≥5
            cout << i << " " << s / y << endl;  // 输出满足条件的方案
        }
    }
    
    return 0;
}

思考

  • 该问题比实验一增加了更多条件:霸王龙数量≥三角龙数量,总数≥5
  • 方法二同样通过消除内循环提高了效率
  • 注意输出顺序的要求:霸王龙数量从少到多,这决定了外循环的遍历顺序
  • 当问题条件较多时,代码中的条件判断需要准确反映所有要求