You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

63 lines
3.1 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
//方案数量,预计,注意此处可不是n的数据上限而是可能的方案数量尽量开大防止出错黄海就因为开小了挂掉
const int M = 20; //配料的数量本题目是10为了开大一点数组加了10
int a[N][M]; //保存所有可行的方案,描述第i种方案放过二维的第一个格子0第二个格子1表示i种方案中第一个配料用多少克
int path[M]; //记录当前正在计算的方案.本题经验数组开小了会出错n值错乱的诡异问题描述当前方案每一种配料用多少克
/**
C++语言中数组越界访问系统不会给出任何的提示,程序员可以超出数组边界进行读/写从而造成内存的混乱,
而这种错误对初学者来说是很容易出现的、而又偏偏是很难调试的,因为系统不会给出错误的提示,所以就这样使用数组是不安全的。
*/
/**
对比暴力无脑大模拟dfs的使用范围更广很好理解比如我们不知道要多少轮轮次数需要输入进来我们就没有办法预先控制循环的层数
而dfs天生就是可以处理不定层数的
*/
int n, cnt; //美味值,可行方案数量
/**
* 假设我们在面临一种通用的场景,也就是通常说的“一般性场景”
* (1)我们正在准备放入第step件调料目前的情况是没放此种调料之前的美味值是sum
* (2)第step件调料我们可以选择放入123三种数量需要用循环把这些都尝试一遍。
* (3)如果我们选择完了数量i之后我们需要继续向下一种调料出发但情况已经发生了变化变成处理第
* step+1件调料同时总和也变成了sum+i
* (4)当处理完第10件调料后也就是step=9(因为step是从0开始的)时,再向下就是递归出口,在这里判断是不是一组可行解。
*/
//step为第几种调料sum目前的配料之和
void dfs(int step, int sum) {
if (step == 11) { //当10种调料都分析完了
//如果配料之和等于输入值;
//使用memcpy更简单,参数:目标数组,源数组,长度
if (sum == n)memcpy(a[cnt++], path, sizeof path);
//不管等不等,都需要返回了,递归的出口
return;
}
//在当前step下就是在讨论某一种调料时面临三种选择123
for (int i = 1; i <= 3; i++) {
path[step] = i; //第step种调料的配料为i
dfs(step + 1, sum + i); //递归,对下一种调料做同样的分析
}
}
int main() {
cin >> n;
//从第1步开始目前总和是0
dfs(1, 0);
//输出方案个数
cout << cnt << endl;
//再输出具体的方案
if (cnt > 0) {
for (int i = 0; i < cnt; i++) {
for (int j = 1; j <= 10; j++)
cout << a[i][j] << " ";
cout << endl;
}
}
return 0;
}