晴天的魔法樂園——自然數分解之最大積(深度優先+剪枝)

題目鏈接:https://judger.net/problem/1062

Problem Description

給定一個正整數N,將它表示成至少兩個正整數之和(即N=a1+a2+…+ak, k > 1),求a1 × a2 × … × ak的最大值。
例如對N=4來說,共有下面4種不同的方案:
4=1+1+1+1
4=1+1+2
4=1+3
4=2+2
其中最大的乘積是最後一種,最大乘積是2×2=4。

Input

每個輸入文件一組數據。
第一行爲一個正整數N(2<=N<=20)。

Output

輸出一個正整數,表示a1 × a2 × … × ak的最大值。

Sample Input 1

2

Sample Output 1

1

Sample Input 2

4

Sample Output 2

4

Sample Input 3

6

Sample Output 3

9

1、分析

        這道題目和浙大PAT甲級真題有點相似,PAT.A.1103 Integer Factorization (30 分),用同樣的方法即可。如果使用枚舉法肯定是不現實的,採用深度優先搜索+剪枝是一個比較好的方法。由於每次進行遞歸的時候都有一個臨時乘積變量,因此枚舉的範圍應該是1~N-1,不能是0~N。

2、代碼

①本題代碼:

#include<stdio.h>
int maxProduct = 0, N;
//index爲當前索引,sum爲當前選出的整數和,product爲當前積 
void DFS(int index, int sum, int product){
	if(sum == N){		//找出的幾個數的和剛好等於N 
		if(product > maxProduct){	//找出最大積 
			maxProduct = product;
		}
		return;
	}
	if(sum > N){					//和大於N,直接返回 
		return;
	}
	for(int i = index; i < N; i++){	//從index ~ N-1進行枚舉 
		DFS(i, sum + i, product * i);
	}
}

int main(){
	scanf("%d", &N);
	DFS(1, 0, 1);	//注意搜索的起點 
	printf("%d\n", maxProduct);
	return 0;
}

②如果要保存下來取得最大積時選擇的數據可以採用下面的方法,在遞歸的for循環裏面使用vector進行保存,當數據較多時可以在for裏面剪枝,如下:

#include<stdio.h>
#include<vector>
using namespace std; 
int maxProduct = 0, N; 
void DFS(int index, int sum, int product, vector<int> &ans, vector<int> temp){
	if(sum == N){		 
		if(product > maxProduct){	 
			maxProduct = product;
			ans = temp;
		}
		return;
	}
	if(sum > N){				
		return;
	}
	for(int i = index; i < N; i++){	//從index ~ N-1進行枚舉 
		temp.push_back(i);			//加入temp中 
		if(sum + i > N) break;		//剪枝 
		DFS(i, sum + i, product * i, ans, temp);
		temp.pop_back();			//從temp中除去 
	}
}

int main(){
	scanf("%d", &N);
	vector<int> ans, temp; 
	DFS(1, 0, 1, ans, temp);	//注意搜索的起點
	if(ans.size() == 0) printf("0");	//當輸入1時特判輸出爲0 
	for(int i = 0; i < ans.size(); i++){
		printf("%d", ans[i]);
		if(i < ans.size() - 1) printf(" ");
	} 
	return 0;
}

③如果要求有多少種方案,直接使用一個變量,在每次遞歸的時候出現和等於N的時候+1即可

#include<stdio.h>
int N;
void DFS(int index, int sum, int &ans){
	if(sum == N){
		ans++;	//方案數目+1 
		return;
	}
	if(sum > N){					//和大於N,直接返回 
		return;
	}
	for(int i = index; i < N; i++){	//從index ~ N-1進行枚舉 
		DFS(i, sum + i, ans);
	}
}

int main(){
	scanf("%d", &N); 
	int ans = 0;
	DFS(1, 0, ans);
	printf("%d\n", ans);
	return 0;
}

原文鏈接:https://www.qsp.net.cn/art/177.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章