【ZCMU1400】给报销吗(01背包)

题目链接

解题思路:

这题真是WA到哭泣,感觉一个人拉高了整体的错误率,其实题目思路还是清晰的,但是题目中条件很多容易漏掉,这里罗列一下。

1.每张发票的报销类型只能为A,B,C,有其他类型则此发票作废

2.每张发票的每种报销类型的报销额相加后要<=1000,若大于则此发票作废

3.每张发票的每种报销类型的报销额都不能超过600,即A<=600,B<=600,C<=600

上述条件只要有一个不符合这张发票就不用被记录啦,然后就看成重量和价值是相等的01背包做就可以啦,但是因为背包是整数,所以记得把报销额都转换成整数。

代码:

扫描二维码关注公众号,回复: 2450294 查看本文章
#include<bits/stdc++.h>
#define t 100
using namespace std;
int dp[3000005],v[3000005];
int main()
{
	double Q;
	int N;
	while(~scanf("%lf%d",&Q,&N) && N!=0){
		memset(v,0,sizeof(v));
		memset(dp,0,sizeof(dp));
		int i=0,j,k=0,q;
		double p;
		char s1;
		while(N--){
			int n,flag=1;
			double sum=0,a=0,b=0,c=0;
			scanf("%d",&n);
			while(n--){
				scanf(" %c:%lf",&s1,&p);
				if(s1=='A')a=a+p;
				else if(s1=='B')b=b+p;
				else if(s1=='C')c=c+p;
				else flag=0;
			}
			sum=a+b+c;
			if(flag && sum<=1000 && a<=600 && b<=600 && c<=600)v[k++]=(int)(sum*t);
		}
		q=(int)(Q*t);
		for(i=0;i<k;i++){
			for(j=q;j>=v[i];j--){
				dp[j]=max(dp[j],dp[j-v[i]]+v[i]);
			}
		}
		printf("%.2f\n",dp[q]/100.0);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39826163/article/details/81208095
今日推荐