HDU 1864 最大报销额(01背包)

题意:现有一笔经费可以报销一定额度的发票。允许报销的发票类型包括买图书(A类)、文具(B类)、差旅(C类),要求每张发票的总额不得超过1000元,每张发票上,单项物品的价值不得超过600元。现请你编写程序,在给出的一堆发票中找出可以报销的、不超过给定额度的最大报销额。 (总发票数<=30)


思路:首先找出所有有效的发票,然后做一次01背包就行了,但是金额是两位小数,所以可以都先乘上100变成整数再去操作。


代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 35;
const int maxm = 35*1005*100;
int a[maxn];
int dp[maxm];

int main(void)
{
    double q;
    int n;
    while(cin >> q >> n)
    {
        if(n == 0) break;
        int cur = 0;
        int M = (int)(q*100);
        for(int i = 0; i < n; i++)
        {
            int costAll = 0, costA = 0, costB = 0, costC = 0;
            int k;
            scanf("%d", &k);
            char kind;
            double x;
            bool ok = 1;
            for(int j = 0; j < k; j++)
            {
                scanf(" %c:%lf", &kind, &x);
                int v = (int)(x*100);
                if(kind == 'A') costA += v;
                else if(kind == 'B') costB += v;
                else if(kind == 'C') costC += v;
                else ok = 0;
                costAll += v;
            }
            if(ok && costA <= 60000 && costB <= 60000 && costC <= 60000 && costAll <= 100000)
                a[cur++] = costAll;
        }
        memset(dp, 0, sizeof(dp));
        for(int i = 0; i < cur; i++)
            for(int j = M; j-a[i] >= 0; j--)
                dp[j] = max(dp[j], dp[j-a[i]]+a[i]);
        printf("%.2f\n", dp[M]/100.0);
    }
    return 0;
}

import java.util.Arrays;
import java.util.Scanner;

public class Main {
	static final int maxn = 35;
	static final int maxm = 35*1005*100;
	static int a[] = new int[maxn];
	static int dp[] = new int[maxm];

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		double q;
		int n;
		while(sc.hasNext()){
			q = sc.nextDouble();
			n = sc.nextInt();
			if(n == 0) break;
			int M = (int) (q*100);
			int cur = 0;
			double x;
			for(int i = 0; i < n; i++)
			{
				int k, v, costAll = 0, costA = 0, costB = 0, costC = 0;
				boolean ok = true;
				k = sc.nextInt();
				for(int j = 0; j < k; j++)
				{
					String str = sc.next();
					v = (int)(100*Double.valueOf(str.substring(2, str.length())));
					char kind = str.charAt(0);
					if(kind == 'A') costA += v;
					else if(kind == 'B') costB += v;
					else if(kind == 'C') costC += v;
					else ok = false;
					costAll += v;
				}
				if(ok && costAll <= 100000 && costA <= 60000 && costB <= 60000 && costC <= 60000)
					a[cur++] = costAll;
			}
			
			Arrays.fill(dp, 0);
			for(int i = 0; i < cur; i++)
				for(int j = M; j-a[i] >= 0; j--)
					dp[j] = Math.max(dp[j], dp[j-a[i]]+a[i]);
			System.out.println(String.format("%.2f", dp[M]/100.0));
		}
	}
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值