小明开了一家糖果店。他别出心裁:把水果糖包成4颗一包和7颗一包的两种。糖果不能拆包卖。 小朋友来买糖的时候,他就用这两种包装来组合。当然有些糖果数目是无法组合出来的,比如要买 10 颗糖。 你可以用计算机测试一下,在这种包装情况下,最大不能买到的数量是17。大于17的任何数字都可以用4和7组合出来。 本题的要求就是在已知两个包装的数量时,求最大不能组合出的数字。 输入: 两个正整数,表示每种包装中糖的颗数(都不多于1000) 要求输出: 一个正整数,表示最大不能买到的糖数 例如: 用户输入: 4 7 程序应该输出: 17
再例如: 用户输入: 3 5 程序应该输出: 7
public class 买不到的数字 { static final int N = 1000 * 100; static int se(int[] da, int a) { int n=0; for(int i=0; i<da.length; i++) { if(da[i]==1){ n++; if(n>=a) return i-a; } else n = 0; } return -1; } static void f(int a, int b) { int[] da = new int[N]; for(int i=0; i<=N/a; i++) { for(int j=0; j<=(N-i*a)/b; j++) { if(i*a + b*j < N) da[i*a+b*j] = 1; } } System.out.println(se(da, a)); } public static void main(String[] args) { f(3,5); f(4,7); f(10,13); f(30,41); f(257,191); } }
这道算法题为什么这样做?求详细注释,谢谢!
其实你只要有点小小的耐心,把n的计算值模拟一次,一切就真相大白了。
函数se模拟计算如下
a=4 | b=7 | |
i | n | return i-a |
4 | 1 | |
7 | 1 | |
8 | 2 | |
11 | 1 | |
12 | 2 | |
16 | 1 | |
17 | 0 | |
18 | 1 | |
19 | 2 | |
20 | 3 | |
21 | 4 | 17=21-4 |
亲爱的大叔,有些变量我都不知道是什么意思啊,肿么模拟呀
@爱编程1314: 拜托。你英文不懂还是JAVA不懂?
我可是没有学过JAVA,只会.NET的菜鸟来着。
直接看着那代码都能蒙出来...
没有哪个变量比较奇怪啊。
@爱编程的大叔: 我是说那些变量定义有什么用,我就是解题的具体思路还没有理清楚,比如说哪行代码是判断不能够买的数字
@爱编程1314:
好吧,既然别人都不愿意现丑,那就只能我来了。
1、这段代码
for(int i=0; i<=N/a; i++) { for(int j=0; j<=(N-i*a)/b; j++) { if(i*a + b*j < N) da[i*a+b*j] = 1; } }
就是很土的一段代码,把所有可以组成的数字的数组无素赋值为1。也就是说以不能组成的数字为下标的数组元素里面的值是0。
然后,System.out.println(se(da, a));
这个函数就是从1开始向上找,直到找到符合条件
if(n>=a) return i-a;
比如4,7, 则i=21时,符合条件,跳出循环,返回17。
@爱编程的大叔: 还是有点不明白,脑袋比较笨,变量n表示什么?为什么n>=a就执行下一句,这个表达式表示什么?为什么是返回i—a而不是其他的呢?请原谅我的笨脑壳,谢谢!
@爱编程1314: w
你看看我上面那个表格的数字,最后5个,能不能看出什么来,
给你15分钟,看不出来再问我。要不你就失去思考的过程了。
@爱编程的大叔: 不好意思大叔,让您久等了,刚刚出去了,看了一下,后面5个i-n都等于17,
@爱编程的大叔: 我明白了大叔,n表示能买的次数连续累加之和只要大于小包的个数,以后的数都可以拆分成能够买的数的组合,那这个组合的数也是可以买的,最大不能买的数就是,满足条件n>=a的临界值i,然后i-a就是最大不能买的数,我这样理解对吗?大叔
@爱编程1314:
你看这样自己思考的过程是不是比我直接给你答案有成就感一些?!
@爱编程的大叔: 嗯,我感觉自己的智商瞬间上升了一个档次,不再是青铜了,而是白银了,多谢大叔的指导,呵呵!