本文前一部分的鏈接
html">http://www.BkJia.com/kf/201105/92329.html
5.准備寫qiongju()函數
因為要解決的問題對時間的要求以及計算對象是21位數,所以不難想象這個函數可能比較復雜。不可能一蹴而就,所以在編寫前首先要考慮測試。
在測試用main()內添加函數調用qiongju();
#ifdef CESHI //測試
int main( void )
{
qiongju();
system("PAUSE");
return 0;
}
#endif //CESHI
把 0_問題.h 中的 #define QIUJIE 中的 QIUJIE 改成CESHI 編譯運行通過 。這表明文件包含及qiongju()函數原型等方面均沒什麼問題。
下面轉到 2_窮舉.c 源文件中,填充那個空著的qiongju()函數定義
6.對窮舉方案的思考
最容易想到的窮舉方案是
方案1.
for(W_ws=最小W位數;W_ws<=最大W位數;W_ws++)
{
//驗算
}
這種方案首先需要解決W位數的表示問題,即設計存儲這種數據的數據類型的問題。
此外還需要考慮這種數據如何賦值、加1及比較大小等問題。
最主要的,還需要解決解的搜索空間過大的問題。
一下子同時解決這幾個問題總是讓人有些生畏(但也並非不能解決),因此暫不考慮。
第二種方案用循環嵌套的方式進行窮舉
方案2.
for(第1位數=1;第1位數<JINZHI;第1位數++)
for(第2位數=0;第2位數<JINZHI;第2位數++)
……
for(第W位數=0;第W位數<JINZHI;第W位數++)
{
//驗算
}
這種方案在一開始不必考慮W位數的表示問題,但解的搜索空間依然很大。
解空間巨大的原因是窮舉給出的是各位數的排列,這是一個相當巨大的數目 ((JINZHI-1)*JINZHI^(W-1),對21位十進制數來說,這個值是9*10^20)。然而各種排列中有相當一部分,其各位數N次方的和是相同的(以3位數為例,110和101各位數的3次方之和都為2),不應該重復計算這些值。
為了避免重復計算這些值,應該只驗算各位數字的各種組合而不是對各位數字的排列進行驗算。為此,可將窮舉的循環結構改良為
方案2-1.
for(第1位數=JINZHI-1;第1位數>0;第1位數--)
for(第2位數=第1位數;第2位數>=0;第2位數--)
……
for(第W位數=第W-1位數;第W位數>=0;第W位數--)
{
//驗算
}
這個結構由於保證了各位數字均不大於前面的各位數字,所以得到的是W位數的各種組合。解的搜索空間大大降低(對21位十進制數,只有14307149(30!/9!/21!-1)種可能)。
這種方案比較形象直觀,容易理解。
收工。
收獲:完成了qiongju()的測試准備。
感想:寫代碼是簡單的,想代碼應該怎麼寫是困難的。用完成代碼的行數來衡量程序員的工作量是愚蠢的。至於博客園把隨筆移出首頁所依據的標准呢?我想恐怕至少也是見仁見智的吧