巡邏隊的士兵

題目:
巡邏的士兵

時間限制:1000MS 內存限制:65536K
提交次數:217 通過次數:58

題型: 編程題 語言: G++;GCC
Description
有N個士兵站成一隊列, 現在需要選擇幾個士兵派去偵察。
爲了選擇合適的士兵, 多次進行如下操作: 如果隊列超過三個士兵, 那麼去除掉所有站立位置爲奇數的士兵,
或者是去除掉所有站立位置爲偶數的士兵。直到不超過三個戰士,他們將被送去偵察。現要求統計按這樣的方法,
總共可能有多少種不同的正好三個士兵去偵察的士兵組合方案。

注: 按上法得到少於三士兵的情況不統計。

1 <= N <= 2的32次方-1

輸入格式
有多行(可能有上百行,儘量優化代碼),每行一個數字N,最後一行是0

輸出格式
對每一行的數字N,輸出針對N的方案數

直到沒有數字

輸入樣例
10
4
0

輸出樣例
2
0

思路:
1,思路實際上就是遞歸,結束條件很明顯,當n<3時返回0,當n=3時返回1,其餘時候則分解爲留下奇數位和留下偶數位。而且,對於每一次的分解操作,實際上就是分爲奇數和偶數兩派,也就是兩個子集相交爲空,所以計算出來的結果沒有重複。
2,太慢怎麼辦,太慢就是由於有大量的重複計算,比如你7遞歸調用4,3。而你8遞歸調用4,4.你會發現有大量重複的計算。如何加快,那就記憶化,就是開一個數組將每次得到結果的值保存下來,以後再次調用的時候就直接return 數組,而不用遞歸了。
爲什麼是遞歸?遞歸會不會造成重和解?

#include<cstdio>
#include<cstring>
#include<cstdlib>
int a[100000002]={0};
int f(int N)
{
	if(N<100000000&&a[N]>0)return a[N];   //如果已經被記錄,直接返回 
	if(N<3)return a[N]=0;     
	else if(N==3)return a[N]=1;
	else                                  //否則,計算並記錄 
	{
		int t=f((N+1)/2)+f(N/2);
		if(N<100000000)a[N]=t;
		return t;
	}			
}
int main()
{
	int N;
	while(1)
	{
		scanf("%d",&N);
		if(N==0)break;
		printf("%d\n",f(N));
	} 
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章