题目背景
猪猪 Hanke 得到了一只鸡。
题目描述
猪猪 Hanke 特别喜欢吃烤鸡(本是同畜牲,相煎何太急!)Hanke 吃鸡很特别,为什么特别呢?因为他有 10种配料(芥末、孜然等),每种配料可以放 1到 3克,任意烤鸡的美味程度为所有配料质量之和。
现在, Hanke 想要知道,如果给你一个美味程度 nn ,请输出这 1010 种配料的所有搭配方案。
输入格式
一个正整数 n,表示美味程度。
输出格式
第一行,方案总数。
第二行至结束,10 个数,表示每种配料所放的质量,按字典序排列。
如果没有符合要求的方法,就只要在第一行输出一个 0。
输入输出样例
输入
11
输出
10
1 1 1 1 1 1 1 1 1 2
1 1 1 1 1 1 1 1 2 1
1 1 1 1 1 1 1 2 1 1
1 1 1 1 1 1 2 1 1 1
1 1 1 1 1 2 1 1 1 1
1 1 1 1 2 1 1 1 1 1
1 1 1 2 1 1 1 1 1 1
1 1 2 1 1 1 1 1 1 1
1 2 1 1 1 1 1 1 1 1
2 1 1 1 1 1 1 1 1 1
说明/提示
对于 100%100% 的数据,n \leq 5000n≤5000。
思路:一开始我想从n出发,对n-10后的部分进行分配,这样能计算出方案数,但不容易输出每个方案,而且没有考虑美味度上界(30),错的离谱,,,
这是我最初的错误代码。
int main()
{
//define variable and initialize
int season[10]={1,1,1,1,1,1,1,1,1,1};
int n,i,j;
long long int res=0;//方案数
//get data
scanf("%d",&n);
//calculate
if(n==10)
res=1;
else if(n<10)
res=0;
else if(n>10)
{
n-=10;//得到10以外多出的部分
res+=10;//多出的部分整体分配到一种调料中,10选1,共十种(error:没有考虑一种调料最多放三克)
for(i=1;i<=n/2;i++)//不断分出一部分(分出1,2,3……)方案数即组合数(error:没有考虑一种调料最多放三克)
{
int tem=n;
tem-=i;j=2;//分为j部分,一部分为tem,剩余部份全为i
while(tem>0&&j<=10)
{
res+=f(10,j);//函数f计算组合数,10选j
j++;
tem-=i;
}
}
}
// output result
printf("%d\n",res);
return 0;
}
改正后:
搜到的大佬的答案,代码如下:
#include<cctype>
#include<cstdio>
using namespace std;
const int maxn = 13;
char ans[1000000 + 5];
char *anscur = ans;
int nums[maxn]; // 当前调料
int cnt = 0; // 方案数
void printans(){
int offset;
for(int i = 0; i < 10; i++){
sprintf(anscur, "%d %n", nums[i], &offset);//%n 作用:将输入的数据项数存入offset中
anscur += offset;//使指针指向下一次输入的起始位 用%n就避免了使用strlen,降低时间复杂度
}
sprintf(anscur, "\n%n", &offset);
anscur += offset;
}
void dfs(int cur, int left){ // 深搜过程
if(cur == 10 && !left){ // 已经搜到第10层,这个时候调料恰好加完
cnt++; // 方案数+1
printans(); // 将方案输出到字符串里面
return;
}
int &i = nums[cur]; // 声明别名(引用)
for(i = 1; i <= 3; i++){
if((10 - cur - 1) * 3 + i < left) continue; // 剪枝。如果剩下的调料都加3克都不够,说明不可能
if((10 - cur - 1) + i > left) break; // 剪枝。如果剩下的调料都加一克也超量,说明不可能
dfs(cur + 1, left - i);
}
}
int main(){
int n;
scanf("%d", &n);
if(10 <= n && n <= 30) dfs(0, n);// 如果n不在[10, 30]范围内,说明不可能有解,跳过搜索
printf("%d\n%s", cnt, ans); //输出答案
}
//最终用时34ms,最长一个点10ms,快了差不多几十倍。
正解:深度搜索 剪枝操作和字符串存储,大大降低复杂度