藍橋杯 程序設計_6

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章