Bootstrap

【洛谷枚举算法】P2089烤鸡

由于每种配料的用量范围是 1 到 3 克,且有 10 种配料,我们可以使用深度优先搜索(DFS)枚举所有可能的配料组合,然后筛选出美味程度等于给定值 n 的组合。

【题目】:
在这里插入图片描述

【算法思路】

  • 全局变量

MAX:常量,代表配料的种类数量,本题中固定为 10。

n:用于存储输入的给定美味程度,该值决定了满足条件的配料组合。

ans:定义为二维向量 std::vector<std::vector<int>>,其作用是存储所有符合要求(即配料总质量等于给定美味程度 n)的配料组合。

path:是一个一维数组,数组长度为 MAX,用来记录在深度优先搜索过程中当前正在探索的配料组合情况。

  • 深度优先搜索函数

函数参数

  • step:表示当前正在考虑的配料编号,取值范围是从 0 到 MAX - 1
  • sum:记录到当前步骤为止,所使用配料的总质量。

搜索范围:基于配料的种类数,本题中 MAX 被设定为 10,意味着需要对 10 种配料进行组合尝试。

存储结构:使用二维向量 ans 来存储所有满足条件的配料组合,无需额外定义二维数组。

标记情况:此问题无需使用标记数组。原因在于 “烤鸡” 问题是对配料组合进行枚举,每种配料的使用情况相互独立,且每个配料都必须被考虑一次,不会出现重复访问同一状态而陷入无限循环的情况。

递归逻辑

  • 未考虑完 10 种配料时:对于当前的配料(编号为 step),其用量有 1 克、2 克、3 克这三种选择。依次枚举这三种用量,将当前配料的用量记录到 path[step] 中,然后递归调用深度优先搜索函数 dfs(step + 1, sum + 当前用量),继续处理下一种配料。
  • 考虑完 10 种配料时:检查当前配料组合的总质量sum是否等于给定的美味程度n
    • 若相等,说明找到了一种满足条件的配料组合。将 path 数组中的内容复制到一个临时向量 temp 中,再把 temp 添加到 ans 向量里。
    • 若不相等,表明该配料组合不符合要求,直接返回,结束当前搜索路径,回溯到上一层继续尝试其他组合。
  • 输出:①从第0种配料开始搜索,最后输出满足条件的配料组合的数量;

②使用范围for循环函数输出每种配料组合

【代码示例】

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;

const int MAX = 10;//范围:配料的种类数 
int n;//给定的美味程度 
vector<vector<int>> ans;//存储所有满足条件的配料组合
int path[MAX];//记录当前正在搜索的配料组合

// 深度优先搜索函数
void dfs(int step,int sum){
	//当已经考虑完10种配料
	if(step == MAX){ 
		if(sum == n){//检查总质量是否等于给定的美味程度
			vector<int> temp;
			//将当前的配料组合添加到临时向量中
			for(int i=0;i<MAX;i++){
				temp.push_back(path[i]);
			} 
			//将临时变量添加到结果数组中
			ans.push_back(temp); 
		}
		return;
	} 
	//枚举当前配料的用量
	for(int i=1;i<=3;i++){
		path[step] = i;//设置当前配料的用量
		dfs(step + 1,sum + i);//递归调用处理下一种配料 
	} 
} 

int main(){
	cin>>n;//读取输入的美味程度 
	dfs(0,0);//从第0种配料开始,总质量初始为0
	cout<<ans.size()<<endl;//输出满足条件的配料组合的数量
	
	//输出每种配料组合
	for(const auto& vec : ans){
		for(int i=0;i<MAX;i++){
			cout<<vec[i];
			if(i < MAX-1){
				cout<<" ";
			}
		}
		cout<<endl;
	}
	
	return 0;
}
;