公司发了某商店的购物券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;
}