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