现在的位置: 首页 > 综合 > 正文

hdu 1864 最大报销额(01背包d )

2014年04月05日 ⁄ 综合 ⁄ 共 966字 ⁄ 字号 评论关闭

http://acm.hdu.edu.cn/showproblem.php?pid=1864

这里有让人犯迷糊的地方,可能是题意不清楚。当满足下面条件之一的,这张发票就不能报销,相当于作废:

1.一张发票上有除了 'A' 'B' C"之外还有别的类型的消费

2.这张发票的总总消费大于1000

3.单项物品的价值超过600


这样就变成了01背包问题。即某张发票被报销和不被报销两种情况。

还有就是给定的总额和发票的消费总额都是两位小数,可以先给他们同时扩大100倍,最后输出的时候再缩小100倍。


#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

const int maxn = 3000010;
int dp[maxn];

int chk(char ch)
{
	if(ch == 'A' || ch == 'B' || ch == 'C')
		return 1;
	return 0;
}

int main()
{
	double Q;
	int n,m,v;
	int a[40];
	while(~scanf("%lf %d",&Q,&n))
	{
		if(n == 0) break;
		v = Q*100;		//指定报销额扩大100倍
		for(int i = 1; i <= n; i++)
		{
			scanf("%d",&m);
			double A = 0,B = 0,C = 0,x,s = 0;
			int f = 1;
			char str;
			while(m--)
			{
				scanf(" %c:%lf",&str,&x);
				if(chk(str) == 0) f = 0;
				if(str == 'A') A += x;
				if(str == 'B') B += x;
				if(str == 'C') C += x;
				s += x;
			}
			if(A > 600 || B > 600 || C > 600 || s > 1000 || f == 0)
				a[i] = 0;	//该发票不符合要求,置为0.
			else a[i] = s*100;//否则发票的总价值也扩大100倍
		}
		
		memset(dp,0,sizeof(dp));
		dp[0] = 1;	//初始化。0肯定能达到
		int ans = 0;
		for(int i = 1; i <= n; i++)
		{
			for(int j = v; j >= a[i]; j--)
			{
				if(dp[j-a[i]])
				{
					dp[j] = 1;
					ans = max(ans,j);
				}
			}
		}
		printf("%.2lf\n",ans/100.0);	//最后还原
	}
	return 0;
}

抱歉!评论已关闭.