蓝桥杯 程序设计_6

本文介绍了蓝桥杯程序设计竞赛中的一道题目,要求编写程序找出所有能用1000元购物券购买指定商品的组合方式。文章提供了两种解题思路,包括暴力递归法和优化的递归法,通过先对商品按价格升序排列,以提高效率。并给出了使用优化思路的程序解决方案。
摘要由CSDN通过智能技术生成

        公司发了某商店的购物券1000元,限定只能购买店中的m种商品。每种商品的价格分别为m1,m2,…,要求程序列出所有的正好能消费完该购物券的不同购物方法。

程序输入:

        第一行是一个整数m,代表可购买的商品的种类数。

        接下来是m个整数,每个1行,分别代表这m种商品的单价。

程序输出:

        第一行是一个整数,表示共有多少种方案

        第二行开始,每种方案占1行,表示对每种商品购买的数量,中间用空格分隔。

例如:

        输入:

2

200

300

则应输出:

2

2  2

5  0

        输入:

2

500

800

则应输出:

1

2  0

分析:

        思路1:暴力法。递归或循环出所有可能,计算并保存符合条件的。[优点:思路简单,容易实现;缺点:效率低。]

        思路2:先对输入商口按价格升序排列,然后按先选低价商品再选高价商品递归求解,求解过程中可尽早排除一些不可行解,从而节省时间。[优点:虽然还是用递归实现,

但因较早的排除了一些不可行解,因此较思路1效率高些;缺点:实现较复杂。]

以下为思路2程序:

解:

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <string.h>
#include <vector>

#define MONEY	1000

typedef void	VOID;
typedef int		INT32;
typedef char	INT8;

typedef struct GOODS_ST
{
	INT32 price;	//单价
	INT32 n;		//该商品第几个被输入
}Goods;	//商品

//qsort比较函数
int compare( const void *arg1, const void *arg2 )
{
   
   return (*(Goods *)arg1).price > (*(Goods *)arg2).price;
}

/****************************************************************************
* 函数:calc 																*
* 参数:g:商品结构数组(单价和序号).										*
*	   m:总商品数.															*
*      k:当前计算的商品序号(经排序的g结构数组中的序号).					*
*	   remain:剩余钱数.														*
*	   res:(out)当前已买商品(序号)数组.									*
*      vRes:(out)结果.														*
* 返回值:无.																*
* 功能:计算remain块钱可够买的所有物品组合.									*
*      要求g已按单价升序排列.                                               *
*****************************************************************************/
VOID calc(Goods *g, INT32 m, INT32 k, INT32 remain, INT32 *res, std::vector<INT32> &vRes)
{

	INT32 i,j;
	INT32 r;
	for(i=k; i<m; i++)
	{
		r = remain - g[i].price;
		if(r > 0)
		{
			//当前商品可够买
			res[g[i].n]++;
			calc(g, m, i, r, res, vRes);
			res[g[i].n]--;
		}
		else if(r == 0)
		{
			//得到1种结果
			res[g[i].n]++;
			for(j=0; j<m; j++)
			{
//				printf("%d ", res[j]);
				vRes.push_back(res[j]);
			}
			res[g[i].n]--;

//			printf("\n");
		}
		else
			return;
	}
}

/****************************************************************************
* 函数:f 																	*
* 参数:m:商品数.															*
*	   price:单价(数组).													*
*      vRes:(out)保存结果.													*
* 返回值:无.																*
* 功能:计算MONEY块钱可够买的所有物品组合.									*
*****************************************************************************/
VOID f(INT32 m, INT32 *price, std::vector<INT32> &vRes)
{
	Goods *g;
	INT32 i;
	INT32 *res = (INT32 *)malloc(sizeof(INT32)*m);	//存放每次计算时的结果
	memset(res, 0, sizeof(INT32)*m);

	//初始化g
	g = (Goods *)malloc(sizeof(Goods)*m);
	for(i=0; i<m; i++)
	{
		g[i].price = price[i];
		g[i].n = i;
	}

/*	for(i=0; i<m; i++)
	{
		printf("%d,%d\n", g[i].price, g[i].n);
	}
*/
	qsort((void *)g, (size_t)m, sizeof( Goods ), compare);	//排序g, 按g.price升序

/*
	for(i=0; i<m; i++)
	{
		printf("%d,%d\n", g[i].price, g[i].n);
	}
*/

	calc(g, m, 0, MONEY, res, vRes);	//计算并将结果保存到vRes

	free(g);
	free(res);
}

VOID	PrintRes(std::vector<INT32> &vRes, INT32 m)
{
	INT32 n;
	std::vector<INT32>::iterator it;

	n = vRes.size()/m;

	printf("%d\n", n);

	for(it=vRes.begin(); it!=vRes.end(); ++it)
	{
		printf("%d ", *it);
		if((it-vRes.begin()+1)%m == 0)
			printf("\n");
	}
}

INT32 main(INT32 argc, INT32 *argv[])
{
	INT32 m;	//商品数
	INT32 *price;	//单价
	INT32 i;
	std::vector<INT32> vRes;	//保存最终结果

	printf("请输入商品的种类数...\n");
	scanf("%d", &m);

	price = (INT32 *)malloc(sizeof(INT32)*m);

	printf("请输入商品单价...\n");
	for(i=0; i<m; i++)
		scanf("%d", &price[i]);
	
    f(m, price, vRes);

	printf("\nres:\n");

	PrintRes(vRes, m);

	free(price);

	return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值