題目如下:
寫一個程式, 要求功能:求出用1,2,5這三個數不同個數組合的和為100的組合個數。
拿到這個題目,很多人馬上就會在腦海裡,建立一個運算式:x + 2*y + 5*z = 100;那麼只要用程式解出這個運算式,是否就可以解答這個題目呢。
int number = 0,x = 0,y = 0,z = 0; for(x = 0;x <= 100;x++) for(y = 0;y <= 50;y++) for(z = 0;z <= 20;z++) { if(x + 2 * y + 5 * z == 100) { number++; } }
這樣解答是可以解答出答案,但是效率是否太低了一點(一共要迴圈迴圈100*50*20次)。
那麼不妨我們先分析一下,再來考慮如何解答這個問題:
因為x+2y+5z=100所以x+2y=100-5z,且z=20x=100 y=50所以(x+2y)=100,且(x+5z)是偶數對z作迴圈,求x的可能值如下:z=0, x=100, 98, 96, ... 0z=1,x=95, 93, ..., 1z=2, x=90, 88, ..., 0z=3, x=85, 83, ..., 1z=4, x=80, 78, ...,0......z=19, x=5, 3, 1z=20, x=0因此,組合總數為100以內的偶數+95以內的奇數+90以內的偶數+...+5以內的奇數+1,即為:(51+48)+(46+43)+(41+38)+(36+33)+(31+28)+(26+23)+(21+18)+(16+13)+(11+8)+(6+3)+1某個偶數m以內的偶數個數(包括0)可以表示為m/2+1=(m+2)/2某個奇數m以內的奇數個數也可以表示為(m+2)/2。
int number = 0;int m = 0;for(m = 0;m <= 100;m+=5){number += (m + 2)/2;}
這個程式,只需要迴圈21次, 兩個變數,就可以得到答案,比上面的那個程式高效了許多倍----只是因為作了一些簡單的數學分析這再一次證明了:電腦程式=資料結構+演算法,而且演算法是程式的靈魂,對任何工程問題,當用軟體來實現時,必須選取滿足當前的資源限制,使用者需求限制,開發時間限制等種種限制條件下的最優演算法。而絕不能一拿到手,就立刻用最容易想到的演算法編出一個程式了事。
下面是我在CFree上調試用的原始碼,希望對大家有用。
#include <stdio.h>int main(int argc, char *argv[]){#if 1int number = 0;int m = 0;for(m = 0;m <= 100;m+=5){number += (m + 2)/2;}#else int number = 0,x = 0,y = 0,z = 0; for(x = 0;x <= 100;x++) for(y = 0;y <= 50;y++) for(z = 0;z <= 20;z++) { if(x + 2 * y + 5 * z == 100) { number++; } }#endifprintf("number = %d\n",number);return 0;}