【题解】【枚举】——烤鸡

烤鸡

通往洛谷的传送门

题目背景

猪猪 Hanke 得到了一只鸡。

题目描述

猪猪 Hanke 特别喜欢吃烤鸡(本是同畜牲,相煎何太急!)Hanke 吃鸡很特别,为什么特别呢?因为他有 10 10 10 种配料(芥末、孜然等),每种配料可以放 1 1 1 3 3 3 克,任意烤鸡的美味程度为所有配料质量之和。

现在, Hanke 想要知道,如果给你一个美味程度 n n n ,请输出这 10 10 10 种配料的所有搭配方案。

输入格式

一个正整数 n n n,表示美味程度。

输出格式

第一行,方案总数。

第二行至结束, 10 10 10 个数,表示每种配料所放的质量,按字典序排列。

如果没有符合要求的方法,就只要在第一行输出一个 0 0 0

输入输出样例

输入 #1

11

输出 #1

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\% 100% 的数据, n ≤ 5000 n \leq 5000 n5000

解法1.直接枚举

1.1.题意解析

    使用最简单粗暴的枚举就能解决。

    这里有一个节省时间的小技巧:使用宏函数。

    话不多说,直接看代码示例。

1.2.AC代码

#include<bits/stdc++.h>
using namespace std;
#define rep(i) for(int i=1;i<=3;i++)//定义宏函数
int main()
{
    int n,ans=0;
    scanf("%d",&n);
    rep(a)rep(b)rep(c)rep(d)rep(e)rep(f)rep(g)//使用宏函数
	    rep(h)rep(i)rep(j)
            if(a+b+c+d+e+f+g+h+i+j==n)
                ans++;
    if(ans==0)
    {
    	printf("0");
    	return 0;
	}
    printf("%d\n",ans);
    rep(a)rep(b)rep(c)rep(d)rep(e)rep(f)rep(g)
	    rep(h)rep(i)rep(j)
            if(a+b+c+d+e+f+g+h+i+j==n)
                printf("%d %d %d %d %d %d %d %d %d %d\n",a,b,c,d,e,f,g,h,i,j);
	return 0;
}

解法2.剪枝优化

2.1.题意解析

    当然,虽然上面的代码已经可以通过此题了,但为了拓宽眼界,还是给大家提供一种剪枝思路。

    我们可以发现,每个变量在枚举时,都有必要留下充足的空间给后面的变量。比如a,后面的九个变量加起来最多需要27,所以a的初值就可以设成n-27b也同理,它不仅要给后面的八个变量留24 ,还要给a留下空间。其它也同理。

    至于上限,还是拿a举例。a后面的九个变量加起来最少需要9,所以a的上限就是n-9,其它同理。

    注意:此处rep的定义需要改成这样:
#define rep(i,a,b) for(int i=max(1,a);i<=min(3,b);i++)
想一想,为什么?

    最后,我们可以使用一个数组li把答案缓存下来,避免重复计算。

2.2.AC代码

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=max(1,a);i<=min(3,b);i++)
int n,ans,li[5010][10];
int main()
{
    cin>>n;
    rep(a,n-27,n-9)
    rep(b,n-24-a,n-8-a)
	rep(c,n-21-a-b,n-7-a-b)
	rep(d,n-18-a-b-c,n-6-a-b-c)
	rep(e,n-15-a-b-c-d,n-5-a-b-c-d)
	rep(f,n-12-a-b-c-d-e,n-4-a-b-c-d-e)
	rep(g,n-9-a-b-c-d-e-f,n-3-a-b-c-d-e-f)
	rep(h,n-6-a-b-c-d-e-f-g,n-2-a-b-c-d-e-f-g)
	rep(i,n-3-a-b-c-d-e-f-g-h,n-1-a-b-c-d-e-f-g-h)
	rep(j,n-a-b-c-d-e-f-g-h-i,n-a-b-c-d-e-f-g-h-i)
	{
        li[ans][0]=a;li[ans][1]=b;li[ans][2]=c;li[ans][3]=d;
        li[ans][4]=e;li[ans][5]=f;li[ans][6]=g;li[ans][7]=h;
        li[ans][8]=i;li[ans][9]=j;
		ans++;
    }
    cout<<ans<<endl;
    for(int i=0;i<ans;i++)
    {
    	for(int j=0;j<10;j++)
    	    cout<<li[i][j]<<" ";
    	puts("");
	}
    return 0;
}

喜欢就订阅此专辑吧!

【蓝胖子编程教育简介】
蓝胖子编程教育,是一家面向青少年的编程教育平台。平台为全国青少年提供最专业的编程教育服务,包括提供最新最详细的编程相关资讯、最专业的竞赛指导、最合理的课程规划等。本平台利用趣味性和互动性强的教学方式,旨在激发孩子们对编程的兴趣,培养他们的逻辑思维能力和创造力,让孩子们在轻松愉快的氛围中掌握编程知识,为未来科技人才的培养奠定坚实基础。

欢迎扫码关注蓝胖子编程教育
在这里插入图片描述

  • 15
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值