1 2 5组合100,有多少种方法
問題描述:用隨意多個1 2 5三個數字的組合,使其值為100,有多少種組合方法?
基礎解法:窮舉法,1窮舉100次,2窮舉50次,5窮舉20次,這種方法總共窮舉的次數為100*50*20=100 000,性能太差,但是為了以后描述問題,先給出窮舉法的代碼:
?
for(int i = 0; i <= 100; i += 5){for(int j = 0; j <= 100; j += 2){for(int k = 0; k <= 100; k++)if(i + j + k == 100)count++;} }?
?進階解法:通過對窮舉法進行考察,在窮舉的過程中j并不是每次都循環50次,而是隨著i的增加循環次數不斷減小,可以動態計算其循環次數為(100 - i) / 2,對于1的循環次數為可以動態計算為(100 - i - j),通過這個描述可以得到一個新的解法。
?
for(int i = 0; i <= 100; i += 5){for(int j = 0; j <= 100 - i; j += 2){for(int k = 0; k <= 100 - i - j; k++)if(i + j + k == 100)count++;} }?
?進一步優化:通過對上述算法的進一步分析,其實對1沒有必要循環,只要i+j <= 100肯定存在一種解法,也就是說1肯定能補全差值。因此對1的循環是沒有必要的。
?
for(int i = 0; i <= 100; i += 5){for(int j = 0; j <= 100 - i; j += 2){count++; }?
最優解法:通過對上述優化再進一步分析,對于2,是否有必要循環呢?其實我們只要知道100 - i對于2的倍數就行了,小于這個倍數100 - i - j可以用1來補全。因此可以有(100 - i) / 2種組合。考慮到i的個數可以為0,因此應該用這個倍數加1。因此我們只需要20次循環就可以找到總的倍數了。算法如下:
?
?
for(int i = 0; i <= 100; i += 5){count += (100 - i + 2) / 2; //其也可以寫成count += ((100 - i) / 2 + 1) }?
其實通過這個小的編程題的一步步優化,我們已經在使用動態規劃的思想了,其思想的核心就是剪去一些不必要的計算,在進階解法中,我剪掉了不必要的循環次數,在進一步優化中我們剪掉了1的循環,最優解法中我們將對2的循環也剪掉了,形成了最好的解決辦法。
總結
以上是生活随笔為你收集整理的1 2 5组合100,有多少种方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++ STL 算法精选之查找篇
- 下一篇: 一个简单的反射拷贝一份新的实体类