Medicine (01多维背包)

Description


Does it arouse you some painful memory when you see this topic? Don’t worry,Because we won’t let you take medicine today.


As we all know, we get sick sometimes just because our bodies lack of some elements. As long as we supply these elements, the disease will disappear. Now we suppose there are three important elements. A doctor can diagnose how many elements a patient should take. He will also tell you how many quantities of each medicine there are in the storeroom.


Therefore, your task is to calculate the minimal quantity pills of medicine a patient should take if he wants to recover. Because the medicine have side effect, every kind of medicine can only take one pill.


Input


The first line contains an integer n(n<=100), which represents there are n kind of medicine in the storeroom.


The next line contains three integers in order they mean the minimal quantities of the three important elements a patient should take. The quantities will not larger than 20.


The next following n lines contain three integers each, which represent each element’s supply in this kind of medicine.


Output


For each test case you should output an integer in a line, which means the minimal number of pills the patient should take.


If the medicine in the storeroom cannot let the patient get recover, output -1.


Sample Input

3
2 3 5
1 2 3
2 1 2
3 1 6
2
1 2 3
1 2 2
2 1 0
0


Sample Output

2
-1


Hint


For the first sample ,the patient lake of 2 quantities of the first important elements,3 and 5 quantities of the second and the third elements.

If the patient takes the first two kinds of medicine, he can supply 2, 3 and 5 quantities of the elements. So he can get recover.


题意就是用户输入药的类数n,第二行输入病人缺的三种元素的情况,后面几行就是每种药能补的元素的量。让你输出最少要用多少要才能补完,没法补完输出-1


首先它是01最小背包,即每种东西只能取一个,但是要让价值最小,所以状态转移方程的符号要反过来,且初始状态时,除了第一个值为0,其他的值均为INF,这样才能进行正常的大小关系对比。

其次他要补充三种元素,相当于背包有三种限制,所以dp数组要开三维,遍历的时候要有三个for。有还有这道题限制是可以超的,也就是如果背包爆了就置为放满即可。

这道题的价值是每个药片1.

有了这些准备后就可以开写了

#include<stdio.h>
 
const int INF=200;
const int MAXCOST=30;
const int MAXNUM=200;
int dp[MAXCOST][MAXCOST][MAXCOST];
int cost1[MAXNUM];
int cost2[MAXNUM];
int cost3[MAXNUM];
 
 
int main()
{
	int n;
	scanf("%d",&n);
	while(n)
	{
		int c1,c2,c3;
		scanf("%d%d%d",&c1,&c2,&c3);
		for(int i=0;i<=c1;i++)
		for(int j=0;j<=c2;j++)
		for(int k=0;k<=c3;k++)
		dp[i][j][k]=INF;
		dp[0][0][0]=0;
		for(int i=1;i<=n;i++)
		scanf("%d%d%d",&cost1[i],&cost2[i],&cost3[i]);
		for(int i=1;i<=n;i++)
		for(int j=c1;j>=0;j--)
		for(int k=c2;k>=0;k--)
		for(int l=c3;l>=0;l--)
		{
			int f1=j-cost1[i]<0?0:j-cost1[i];//爆了就置为0也就是不会爆
			int f2=k-cost2[i]<0?0:k-cost2[i];
			int f3=l-cost3[i]<0?0:l-cost3[i];
			if(dp[j][k][l]>dp[f1][f2][f3]+1)
			dp[j][k][l]=dp[f1][f2][f3]+1;
		}
		if(dp[c1][c2][c3]==INF) printf("-1\n");
		else printf("%d\n",dp[c1][c2][c3]);
		scanf("%d",&n);
	}
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值