經過一夜難以入眠的煎熬,我戴着熊貓眼滾下牀,打開電腦,想着昨天那道做不出的題目,心裏有所不甘。於是,有了今天。
今天,我一打開電腦,進入oj系統,看着題目,信心滿滿。於是,有了以下的總結:
①這是一支開啓我訓練之門的鑰匙:
=================================================================================================================
題目描述如下:
有N個士兵站成一隊列, 現在需要選擇幾個士兵派去偵察。爲了選擇合適的士兵, 多次進行如下操作: 如果隊列超過三個士兵, 那麼去除掉所有站立位置爲奇數的士兵, 或者是去除掉所有站立位置爲偶數的士兵。直到不超過三個戰士,他們將被送去偵察。現要求統計按這樣的方法,總共可能有多少種不同的正好三個士兵去偵察的士兵組合方案。
注: 按上法得到少於三士兵的情況不統計。1 <= N <= 2的32次方-1
輸入格式
有多行,每行一個數字N,最後一行是0
輸出格式
對每一行的數字N,輸出針對N的方案數
直到沒有數字
輸入樣例
10
4
0
輸出樣例
2
0
=================================================================================================================
思考過程:
這裏是奇數分一半,偶數分一半,那麼我們可以這樣思考:
“等價轉換”思想:實際上這種做法等同於分左右兩半。
“遞歸“思想:你想一下,分成兩半後,又是同樣的問題(即繼續分兩半)--所謂的子問題,一直到不能或者不需要再分爲止。
=================================================================================================================
細節上引發的問題:
以上思考形成的算法會帶來一個問題:如果數據過大,那麼該程序的運行時間是難以接受的。
解決方法:
”記憶搜索“思想:當數據很大的時候,你會容易發現”數據小的部分“已經重複計算了很多次了,所以這種思想就是"把重複計算很多次的結果給儲存起來,等到以後
處理時遇到相同的問題,我們就可以直接拿結果來用,而不用再重複計算“。
其實”記憶搜索“這種思想在很多方面都有體現(特別是在遞歸上的應用):求高次冪運算(例如:2的100次方),fibnacci數列的非遞歸求法,給範圍求素數個數etc。
=================================================================================================================
源代碼:
#include <stdio.h>
//傳說中的記憶搜索,能夠解決一些超時問題(出現多次重複計算)
int record[10000];
int DealWith(int m, int n)
{
int tmp = n - m + 1;
if (tmp < 10000 && record[tmp] != -1)
return record[tmp];
else if ( tmp < 3)
return 0;
else if ( tmp == 3)
return 1;
else {
int ct = DealWith(m, m + tmp / 2 - 1) + DealWith(m + tmp / 2, n);
if ( tmp < 10000 )
record[tmp] = ct;
return ct;
}
}
int main()
{
for (int i = 0; i < 10000; ++i)
record[i] = -1;
int n;
while ( scanf( "%d", &n ) && n != 0 ) {
printf("%d\n", DealWith( 1, n ) );
}
return 0;
}
=================================================================================================================