fortran fortran中文资料网
手气不错
Article

025.nestedloop_嵌套循环实践

2026年7月19日基础级

嵌套循环是把一个循环放入另一个循环体中的结构。外层循环先固定一种选择,内层循环再枚举下一种选择,适合系统检查多种数量组合、坐标组合和参数组合。

本文用一个找零问题实践嵌套循环:顾客支付100元,购买5元商品后需要找零95元。假设商家拥有数量不限的50元、20元、10元、5元和1元纸币,并且只比较各面额的数量,不区分纸币交付顺序。

本篇先让程序完整枚举五种纸币的数量组合,下一篇《算法初识》再讨论如何减少不必要的枚举。

本文代码

! 嵌套循环枚举95元找零的纸币组合。
! 假设各面额数量不限,且不区分纸币发放顺序。
program nestedLoopChangeDemo
  implicit none

  integer :: changeAmount
  integer :: fiftyCount
  integer :: twentyCount
  integer :: tenCount
  integer :: fiveCount
  integer :: oneCount
  integer :: totalAmount
  integer :: solutionCount
  integer :: resultUnit
  integer :: ioStatus

  changeAmount = 95
  solutionCount = 0

  open (newunit=resultUnit, file="result.txt", status="replace", &
        action="write", iostat=ioStatus)
  if (ioStatus /= 0) error stop "无法打开result.txt"

  write (resultUnit,"(A,I3,A)") "找零金额:", changeAmount, " 元"
  write (resultUnit,"(A)") "前12种方案:"

  ! 每一层循环固定一种面额的数量,再进入下一层。
  do fiftyCount = 0, changeAmount / 50
    do twentyCount = 0, (changeAmount - 50 * fiftyCount) / 20
      do tenCount = 0, (changeAmount - 50 * fiftyCount - &
                        20 * twentyCount) / 10
        do fiveCount = 0, (changeAmount - 50 * fiftyCount - &
                          20 * twentyCount - 10 * tenCount) / 5
          do oneCount = 0, (changeAmount - 50 * fiftyCount - &
                            20 * twentyCount - 10 * tenCount - 5 * fiveCount)

            totalAmount = 50 * fiftyCount + 20 * twentyCount + &
                          10 * tenCount + 5 * fiveCount + oneCount

            if (totalAmount == changeAmount) then
              solutionCount = solutionCount + 1
              if (solutionCount <= 12) then
                write (resultUnit,"(A,I3,A,I3,A,I3,A,I3,A,I3)") &
                  "50元=", fiftyCount, " 20元=", twentyCount, &
                  " 10元=", tenCount, " 5元=", fiveCount, &
                  " 1元=", oneCount
              end if
            end if

          end do
        end do
      end do
    end do
  end do

  write (resultUnit,"(A,I3,A)") "全部方案数量:", solutionCount, " 种"
  close (resultUnit)
end program nestedLoopChangeDemo

代码结构

  • changeAmount保存待找零金额95;solutionCount保存已经找到的方案数量。
  • 五层do循环分别枚举50元、20元、10元、5元和1元纸币的数量,外层循环固定一种面额后,内层循环继续枚举剩余面额。
  • 每一层循环的上限都根据剩余金额计算,因此不会枚举已经超过95元的组合。
  • 最内层固定oneCount后,程序计算totalAmount;金额恰好等于95时,才把方案数量加1。
  • resultUnit负责打开、写入和关闭result.txt,程序正常运行时不在终端输出结果。
  • solutionCount <= 12只限制写入的示例数量,不限制统计数量;程序仍会继续遍历并统计全部方案。

编译运行

(base) hong@hongdeMacBook-Pro 025.nestedLoop % gfortran -Wall -Wextra -std=f2018 exampleNestedLoop.f90
(base) hong@hongdeMacBook-Pro 025.nestedLoop % ./a.out
(base) hong@hongdeMacBook-Pro 025.nestedLoop % cat result.txt
找零金额: 95 元
前12种方案:
50元=  0 20元=  0 10元=  0 5元=  0 1元= 95
50元=  0 20元=  0 10元=  0 5元=  1 1元= 90
50元=  0 20元=  0 10元=  0 5元=  2 1元= 85
50元=  0 20元=  0 10元=  0 5元=  3 1元= 80
50元=  0 20元=  0 10元= 0 5元=  4 1元= 75
50元=  0 20元=  0 10元= 0 5元=  5 1元= 70
50元=  0 20元= 0 10元= 0 5元= 6 1元= 65
50元=  0 20元= 0 10元= 0 5元= 7 1元= 60
50元=  0 20元= 0 10元= 0 5元= 8 1元= 55
50元=  0 20元= 0 10元= 0 5元= 9 1元= 50
50元=  0 20元= 0 10元= 0 5元= 10 1元= 45
50元=  0 20元= 0 10元= 0 5元= 11 1元= 40
全部方案数量:294 种

结果分析

程序运行时没有把结果直接打印到终端,而是把示例方案和最终数量写入result.txt。使用cat result.txt可以查看文件内容。

五层循环完整遍历了所有满足上限的非负整数数量组合,最终得到294种方案。下一篇会把其中最后两层循环替换为数学计数公式,比较两种算法的结构。

知识点总结

  • 嵌套循环适合枚举多个离散变量的组合。
  • 每一层循环可以对应一个面额、一个坐标维度或一个独立选择。
  • 根据剩余金额限制循环上限,可以减少无效组合。
  • 方案计数必须明确是否区分排列顺序;本例只区分各面额数量。
  • 程序可以把结果写入文本文件,供后续检查、保存或继续处理。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注