题目描述:

某财务部门结账时发现总金额不对头。很可能是从明细上漏掉了某1笔或几笔。
如果已知明细账目清单,能通过编程找到漏掉的是哪1笔或几笔吗?
如果有多种可能,则输出所有可能的情况。
我们规定:用户输入的第一行是:有错的总金额。
接下来是一个整数n,表示下面将要输入的明细账目的条数。
再接下来是n行整数,分别表示每笔账目的金额。
要求程序输出:所有可能漏掉的金额组合。每个情况1行。金额按照从小到大排列,中间用空格分开。
比如:
用户输入:
6
5
3
2
4
3
1
表明:有错的总金额是6;明细共有5笔。
此时,程序应该输出:
1 3 3
1 2 4
3 4
为了方便,不妨假设所有的金额都是整数;每笔金额不超过1000,金额的明细条数不超过100。 

本体使用的是递归思想,有几个关键点和难点;

首先说关键点:

1.首先我们要读懂题目,要求我们找出超过n元以外的金额的账单,以示例来说,就是要求err_money=6,那么我们就要找到几笔账单(这些账单金额的和为6元),然后依次输出剩下的几笔账单的金额。所以本题两种思路,第一种是dfs找出所有和为6的结果,输出数组剩下的元素;第二种是先算出所有账单金额的总和,减去err_money(也就是一开始输入的6),得出剩下的金额总和,再用dfs找出所欲和为剩余金额的方案,以题目的示例,就是找出和为  (3+2+4+3+1)- 6 的所有方案。本次博客先介绍前者的方法,后者的方法下次再写。

2.递归的思想:这里简单的说就是,找到一个变量或元素,决定选他或者不选他,这样就会产生两种情况,然后递归,记得回溯。

例如:本题中,我们选择的数组num[]   3 2 4 3 1  中。假设我已经我选了num[0],那么对于num[1]来说,我选择了他并于num[0]相加,将会产生第一种情况,得出的和为5;如果不选择他与num[1]相加,那么将会产生第二种情况,就是目前的和为3。

3.要寻找到递归函数的几个参数,首先需要想到有err_money的参数(也就是错误的金额的和),以此来确定是否到达要取的值,然后要想到,我如何才能让我取的几个值的和err_money比较,那我就需要一个current_money的变量与其比较(也就是时刻记录金额的和),而这个current_money的变量我如何为他赋值嘞?因为题目可以认为是一个数组形式(下一篇文章我会介绍将其当成一个集合的形式来写),那么我可以在此产生一个vis[]的数组来依次标记数组的元素,vis数组默认全是0,也就是未访问的意思(vis是visit的缩写,代表访问数组,这个标记法应该是dfs的基础标配了吧,具体可以点击这里),所以认为的状态就是,vis[i]是0,就未被访问(没有加入到current_money中),对应上面的第一种情况,如果被访问了,就被加入变量了,视为第二种方案。因为使用dfs标记法需要回溯,所以每一次要记得将vis[i]重新置为0。所以要加入数组num以及他的元素下标step,以此来不断的找到数组的各个元素,然后分为很多种情况。

难点:

1.题目中要求输出所有可能漏掉的金额组合。金额按照从小到大排列。对于大小排列,可以用Arrays.sort()来解决

所以我们要注意是漏掉的组合,而不是所有情况,对于3 4 和 4 3 其实是算一种的,所以你跑起来可能会发现有两行可能是一样的,然后目前我想出来的方法使用StringBuffer来解决这个问题,但下面的代码没有写上,将会在下一个博客中写。

2.对于dfs函数的出口也很重要,出口条件位置放的不对,可能会使输出乱七八糟,也可以试着遵循一个原则,对于step参数(就是会不断+1递归的那个,本类型也可以粗略理解为数组下标),最好就放在最下面,有些特别情况例外,因为对于数组的判断一般来说是最后的。

import java.util.Arrays;
import java.util.Scanner;public class Test {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int err_money = sc.nextInt();//err_money 指一开始错误的财务总和int current_money = 0;//current_money 指 每一步加或不加的财务总和int n = sc.nextInt();//n 指账目数量int num [] = new int[n];//数组内的元素 指每个账目的具体金额int vis[] = new int[n];//vis数组 用来记录当前的元素是否被访问(即是否被加在current_money中)int step = 0;//step 指num数组中的元素下标for(int i = 0 ; i < num.length ; i++) {num[i] = sc.nextInt();}Arrays.sort(num);f(err_money,num,step, current_money,vis);//起始状况:f(err_money,num,0,0,0);}public static void f(int err_money, int[] num, int step, int current_money, int[] vis) {      if(current_money > err_money) return;if(current_money == err_money) {for(int i = 0 ; i < num.length ; i ++) {if(vis[i] == 0) {System.out.print(num[i]+" ");}}System.out.println();return;}if(step >= num.length) return;vis[step] = 0;f(err_money,num,step+1, current_money,vis);vis[step] = 1;f(err_money,num,step+1, current_money+num[step],vis);vis[step] = 0;//回溯}}

金额查错—某财务部门结账时发现总金额不对头。很可能是从明细上漏掉了某1笔或几笔相关推荐

  1. 金额查错:某财务部门结账时发现总金额不对头。很可能是从明细上漏掉了某1笔或几笔, 如果已知明细账目清单,能通过编程找到漏掉的是哪1笔或几笔吗?

    /** 某财务部门结账时发现总金额不对头.很可能是从明细上漏掉了某1笔或几笔. * 如果已知明细账目清单,能通过编程找到漏掉的是哪1笔或几笔吗? * 如果有多种可能,则输出所有可能的情况. * 我们规 ...

  2. 某财务部门结账时发现总金额不对头。很可能是从明细上漏掉了某1笔或几笔 递归算法

    import java.util.Scanner;public class jianlou {/* * 某财务部门结账时发现总金额不对头.很可能是从明细上漏掉了某1笔或几笔. * 如果已知明细账目清单 ...

  3. 某财务部门结账时发现总金额不对头。很可能是从明细上漏掉了某1笔或几笔。 如果已知明细账目清单,能通过编程找到漏掉的是哪1笔或几笔吗?

    /** 某财务部门结账时发现总金额不对头.很可能是从明细上漏掉了某1笔或几笔.* 如果已知明细账目清单,能通过编程找到漏掉的是哪1笔或几笔吗?* 如果有多种可能,则输出所有可能的情况.* 我们规定:用 ...

  4. 你有结账时发现太贵的尴尬吗?

    请女朋友爸妈吃饭,他们专挑贵的点,吃完饭我就提出了分手. 先别急着喷我小气,事情是这样的: 前阵子女朋友跟我说,她爸妈知道女儿恋爱了,想见我,请我吃个饭. 我也不是扭扭捏捏的人,就赴约了.订在一个比较 ...

  5. 递归法:财务金额漏掉1笔或者几笔(排列组合)

    问题:某财务部门结账时发现金额不对,很可能是从明细上漏掉了一笔或者几笔,如果已知明细账目清单,能通过编程找到漏掉的是哪1笔或者几笔吗? 如果有多种可能,则输出所有可能的情况 我们规定,用户输入的第一行 ...

  6. 结账时提示:不能在对象 't_Balance' 中插入重复键

    用户在使用金蝶专业版财务期末结账时提示: 错误代码:3631(E2FH) Source :Microsoft OLE DB Provider for SQL ServerDetail :违反了 PRI ...

  7. Java 实现循环输入商品编号和购买数量,当输入n时结账,结账时计算应付金额并且找零

    问题描述 循环输入商品编号和购买数量,当输入n时结账,结账时计算应付金额并且找零. 目录 问题描述 (一)定义初始变量 (二)问题分析 (1)循环语句的选择 1. for语句 2. while语句 3 ...

  8. c#实现循环输入商品编号和购买数量,结账时应付金额并找零

    循环输入商品编号和购买数量,系统自动计算每种商品的价钱(单价X数量),并累加总金额. 当输入n时结账(假设享受8折优惠)结账时,根据折扣计算应付金额,输入实付金额,并找零 下面展示一些 内联代码片. ...

  9. 财务部门:你需要多长时间才能够回答老板的这些问题?

    企业经营管理中,对管理决策者来说,有许多问题是希望随时都知道的,下面,我们一起来探讨一下,这些常见的问题,我们怎么来快速回答. 首先,我们来回答以下几个问题:注:这几个问题都可以通过传统的资产负债表与 ...

最新文章

  1. Java最全的思维导图汇总!速度收藏!
  2. 独家 | 利用Auto ARIMA构建高性能时间序列模型(附Python和R代码)
  3. 针对蓝牙4.0 BLE通讯过程的逆向和攻击
  4. cdh 安装_CDH 中为spark 安装 python3
  5. spark常用函数比较
  6. 电源模块的6个优势及其作用
  7. oracle查看存储过程最近编译,Oracle恢复被误编译覆盖的存储过程
  8. Oracle 修改字符集 为ZHS16GBK
  9. SpringBoot | 第六章:常用注解介绍及简单使用
  10. Linux系统下文件与目录操作讲解
  11. 【译】jquery基础教程(jQuery Fundamentals)——(第一部分)概述
  12. Spark 0.9.1 MLLib 机器学习库简介
  13. Javasocket编程步骤,已有千人收藏
  14. VB 连接加密码的ACCESS数据库*.mdb,*.accdb
  15. 简易sql词法分析器和语法分析器
  16. Windows电脑桌面云便签快捷键怎么查看?
  17. mac 命令修改dns服务器,MAC设置DNS的步骤
  18. AMD发布22.9.2驱动,支持《禁闭求生(Grounded)》
  19. Linux:邮箱客户端
  20. 洛谷-P1598- 垂直直方图

热门文章

  1. 计算机的储存容量越大性能就越好吗,内存真的是容量越大频率越大就越好吗?...
  2. 瞄准B端 拉卡拉支付的领先之道
  3. 请求流和响应流(复习笔记)
  4. 计算机能破坏光盘中的系统吗,系统损坏的光盘修复方法_电脑故障修复_电脑知识学习_培训之家...
  5. 修改mendeley字体
  6. 七、T100销售管理之估价与报价管理
  7. linux 查看电池日志,Ubuntu battery 笔记本电池信息查询
  8. JFreeChart导出excel图表工具类
  9. wps纸张大小设置成A4_WPS双面打印时怎么设置奇偶页不同的装订线?方法超简单...
  10. android SD卡检测和热插拔功能