poj 1170 二解 之 背包

题目链接

题意“:有 b种商品 (0 <= b <= 5).,先依次给出 c(1 <= c <= 999,商品编码), k(1 <= k <= 5,需购买的数量),  p (1 <= p <= 999,独立价格)。然后给出s(0 <= s <= 99)种优惠方案,给出的形式如下:每种方案包含n(1 <= n <= 5)种商品,每种商品包含c(编码),k(需购买数量)两个属性,最后是买这个方案中的所有商品给定的数量需要的总价格。问怎样选择优惠方案能最省钱?

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
#define nMAX 6
 /** 五维数组dp表示五种(或小于五种)商品各为相应的数目时总共的价格是多少 */
int dp[nMAX][nMAX][nMAX][nMAX][nMAX];    

/** code[i] = j 表示商品编码为i的商品在数组中的下标为j */ 
int code[1000];

/** 相应的商品数目 */
int num[nMAX];

/** 相应的商品价格 */
int price[nMAX];

int main()
{
	int  i, j, b;
	scanf("%d", &b);
	int c;
	for( i = 0; i < b; i ++ ){
		scanf("%d%d%d", &c, &num[i], &price[i]);
		code[c] = i;
	}

    /** 循环变量数组*/
	int index[5] = {0};

    /** 按照每种商品未优惠的价格对组合购买价格进行初始化 */
	for( index[0] = 0; index[0] <= num[0]; index[0] ++ )
			for( index[1] = 0; index[1] <= num[1]; index[1] ++ )
				for( index[2] = 0; index[2] <= num[2]; index[2] ++ )
					for( index[3] = 0; index[3] <= num[3]; index[3] ++ )
						for( index[4] = 0; index[4] <= num[4]; index[4] ++ ){					
							dp[index[0]][index[1]][index[2]][index[3]][index[4]] = price[0] * index[0] +
								price[1] * index[1] + price[2] * index[2] + price[3] * index[3] + price[4] * index[4];
						}
	int s;
	scanf("%d", &s);
	

	/** 优惠方案中包含的商品的编码和相应所需买的数量 */
	int special_code[nMAX];
	int special_num[nMAX];

	/** 循环每种优惠方案 */
	for( i = 0; i < s; i ++ ){
		/** 第i 种优惠方案所包含的商品种类数 ( < 5) */
		int n;
		scanf("%d", &n);
		for( j = 0; j < n; j ++ ){
			/** 每个种类商品的编码和数目 */
			scanf("%d%d", &special_code[j], &special_num[j] );
		}
		/** 购买优惠方案所有包含的商品的总价格 */
		int p;
		scanf("%d", &p);

		/*
		 注意:即使商品种类数 < 5 该五重循环仍适用
		 */
		for( index[0] = 0; index[0] <= num[0]; index[0] ++ )
			for( index[1] = 0; index[1] <= num[1]; index[1] ++ )
				for( index[2] = 0; index[2] <= num[2]; index[2] ++ )
					for( index[3] = 0; index[3] <= num[3]; index[3] ++ )
						for( index[4] = 0; index[4] <= num[4]; index[4] ++ ){
							/* standard_num[i] = j 表示在去掉该优惠方案所需i 商品的数量后
							 * i 商品剩下的需购买的数量 
							 */
							int  standard_num[5] = {0};
							/** 初始化 */
							for( j = 0; j < 5; j ++ ){
								standard_num[j] = index[j];
							}

							for( j = 0; j < n; j ++ ){
								/* 如有任何一种商品的数量不够该优惠条件所需,
								 * 则放弃使用该优惠条件 
								 */
								if( index[code[special_code[j]]] < special_num[j] )
									break;							
								standard_num[code[special_code[j]]] = index[code[special_code[j]]] - special_num[j];
							}
							if( j == n ){
								/** 动归方程,比较使用该优惠条件前后的价格情况,取较小值 */
								if( dp[index[0]][index[1]][index[2]][index[3]][index[4]] > 
									dp[standard_num[0]][standard_num[1]][standard_num[2]][standard_num[3]][standard_num[4]] + p )
									dp[index[0]][index[1]][index[2]][index[3]][index[4]] = 
									dp[standard_num[0]][standard_num[1]][standard_num[2]][standard_num[3]][standard_num[4]] + p;
							}
						}

	}
	printf("%d\n", dp[num[0]][num[1]][num[2]][num[3]][num[4]]);
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值