POJ1170-DP

Shopping Offers
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 5637 Accepted: 2351

Description

In a shop each kind of product has a price. For example, the price of a flower is 2 ICU (Informatics Currency Units) and the price of a vase is 5 ICU. In order to attract more customers, the shop introduces some special offers.
A special offer consists of one or more product items for a reduced price. Examples: three flowers for 5 ICU instead of 6, or two vases together with one flower for 10 ICU instead of 12.
Write a program that calculates the price a customer has to pay for certain items, making optimal use of the special offers. That is, the price should be as low as possible. You are not allowed to add items, even if that would lower the price.
For the prices and offers given above, the (lowest) price for three flowers and two vases is 14 ICU: two vases and one flower for the reduced price of 10 ICU and two flowers for the regular price of 4 ICU.

Input
Your program is to read from standard input. The first line contains the number b of different kinds of products in the basket (0 <= b <= 5). Each of the next b lines contains three values c, k, and p. The value c is the (unique) product code (1 <= c <= 999). The value k indicates how many items of this product are in the basket (1 <= k <= 5). The value p is the regular price per item (1 <= p <= 999). Notice that all together at most 5*5=25 items can be in the basket. The b+2nd line contains the number s of special offers (0 <= s <= 99). Each of the next s lines describes one offer by giving its structure and its reduced price. The first number n on such a line is the number of different kinds of products that are part of the offer (1 <= n <= 5). The next n pairs of numbers (c,k) indicate that k items (1 <= k <= 5) with product code c (1 <= c <= 999) are involved in the offer. The last number p on the line stands for the reduced price (1 <= p <= 9999). The reduced price of an offer is less than the sum of the regular prices.

Output
Your program is to write to standard output. Output one line with the lowest possible price to be paid.

Sample Input

2
7 3 2
8 2 5
2
1 7 3 5
2 7 1 8 2 10

Sample Output

14
题意:一个人想要去买花,然后店长告诉他我们这有b种花,每种花编号为c,有k朵 每朵价格
然后店有s种优惠,每种优惠是n对(c,k),最后是这样买的价格
问如果要买完这些花,最低价格是多少
思路:五维dp暴力(我同学就是这样过的— — 666)
然后我们发现b的数量很少,所以我们可以化简一下,用六进制 状态压缩来解决这个问题。我们把输入的花转换成六进制之后再用完全背包求一下就是了
六进制数就表示的是第几朵花买了多少
为什么这样可以呢,因为我们要考虑后面的优惠情况,我们在状态转移的时候进行相减的话就能明显的表示出我们要买花的数量。
AC代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int INF=0x7f7f7f7f;
int dp[500000+10],hash[1000+10];
int num[20]={0,1,6,36,216,1296,7776,46656,279936};
struct Node
{
	int i,num,val;
}s[1000];
int main()
{
	int b;
	int n,m,k;
	int ans,x,y,temp;
	while (cin>>b)
		{
			ans=m=0;
			memset(hash,-1,sizeof(hash));
			memset(s,0,sizeof(s));
			memset(hash,-1,sizeof(hash));
			for (int i=1;i<=b;i++)
				{
					scanf("%d%d%d",&temp,&s[i].num,&s[i].val);
					s[i].i=num[i];
					hash[temp]=num[i];		//记录code的进制
					ans=ans+s[i].num*s[i].val;//假如优惠情况的最低比纯买的还贵,这里要比较一下
					m=m+num[i]*s[i].num;	//m表示的是容量,每次把能买的花的数量全部加起来
					s[i].num=num[i];	//每朵花的体积(其实就是六进制从哪个开始)
				}
			scanf("%d",&n);
			for (int i=1;i<=n;i++)
				{
					scanf("%d",&k);
					while (k--)
						{
							scanf("%d%d",&x,&y);
							if (hash[x]==-1) continue;
							s[i+b].num+=hash[x]*y;	//混合的花种
						}
					scanf("%d",&s[i+b].val);
				}
			memset(dp,INF,sizeof(dp));
			dp[0]=0;
	//		cout<<m<<endl;
			for (int i=1;i<=b+n;i++)
				for (int j=s[i].num;j<=m;j++)
					{
						dp[j]=min(dp[j],dp[j-s[i].num]+s[i].val);//多重背包一波。。。
			//			cout<<j<<" -- "<<dp[j]<<endl;
					}
					
			cout<<min(ans,dp[m])<<endl;
		}
	return 0;
}

混合花种:s[i+b].num+=hash[x]y; 因为在六进制情况下这样相加是不会影响其他花种的数量的。而且在后面的背包循环下加减只是表示的是这个花种在这个情况下的数量
比如样例:

num[i](六进制)
第一个 1
第二个 10
混合1 3
混合2 21

m==23(六进制) ,这个可以看出第二朵花最多2朵,第一朵花最多3朵
我们把混合2减去 == 02 还剩下两朵 1 的花

发布了46 篇原创文章 · 获赞 2 · 访问量 3209

猜你喜欢

转载自blog.csdn.net/z1164754004z/article/details/88407391