您的位置:首页 > 其它

【九度】题目1025:最大报销额

2014-02-12 17:04 417 查看
题目地址: http://ac.jobdu.com/problem.php?pid=1025

题目描述:

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

输入:

测试输入包含若干测试用例。每个测试用例的第1行包含两个正数 Q 和 N,其中 Q 是给定的报销额度,N(N<=30)是发票张数。随后是 N 行输入,每行的格式为:

m Type_1:price_1 Type_2:price_2 ... Type_m:price_m

其中正整数 m 是这张发票上所开物品的件数,Type_i 和 price_i 是第 i 项物品的种类和价值。物品种类用一个大写英文字母表示。当N为0时,全部输入结束,相应的结果不要输出。

输出:

对每个测试用例输出1行,即可以报销的最大数额,精确到小数点后2位。

样例输入:

200.00 3

2 A:23.50 B:100.00

1 C:650.00

3 A:59.99 A:120.00 X:10.00

1200.00 2

2 B:600.00 A:400.00

1 C:200.50

1200.50 3

2 B:600.00 A:400.00

1 C:200.50

1 A:100.00

100.00 0

样例输出:

123.50

1000.00

1200.50

来源:

2007年浙江大学计算机及软件工程研究生机试真题

答疑:

解题遇到问题?分享解题心得?讨论本题请访问:http://t.jobdu.com/thread-7749-1-1.html

【解题思路】

其实是01背包,但是在处理基础数据的时候比较复杂。

有以下几种限制。

1、发票必须是A、B、C中的其中一种或者多种,如果出现D、E等等,这张发票就作废了。

2、每张发票上可能开多种类别,但是每种类别钱数不能超过600,总和不得超过1000。

这样处理完毕以后,就知道有多少张发票可以使用。

接下来,问题就简化为有一堆待报销的发票,最多可以报销q,求在限制范围内,可以报销的最大额是多少。

发票要么报销,要么不报销,典型的01背包。

但是,还得注意,因为有类型的限制,有可能会出错。

不妨将double乘倍数取整,这样处理起来方便又不容易出错,这是在很多题目中所使用的技巧之一。

Java AC

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.regex.Pattern;
  
public class Main {
    /*
     * 1025
     */
    public static void main(String[] args) throws Exception {
        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()) {
            double q = scanner.nextDouble();
            int n = scanner.nextInt();
            if (n == 0) {
                break;
            }
            List<Integer> numList = new ArrayList<Integer>();
            while (n > 0) {
                double A = 0;
                double B = 0;
                double C = 0;
                int valid = 0;
                int m = scanner.nextInt();
                while (m > 0) {
                    String a = scanner.next();
                    String typeArr[] = a.split(Pattern.quote(":"));
                    double price = Double.parseDouble(typeArr[1]);
                    if (typeArr[0].equals("A")) {
                        A += price;
                    }else if (typeArr[0].equals("B")) {
                        B += price;
                    }else if (typeArr[0].equals("C")) {
                        C += price;
                    }else {
                        valid = 1;
                    }
                    m--;
                }
                  
                if (valid == 0 && A <= 600.00 && B <= 600.00 && C <= 600.00) {
                    double total = A + B + C;
                    if (total <= 1000.00 && total <= q) {
                        numList.add((int) (total*100));
                    }
                }
                n--;
            }
            int len = numList.size();
            int hunq = (int) (q * 100);
            int dp[] = new int[hunq + 1];
            for (int i = 0; i < len; i++) {
                int tempNum = numList.get(i);
                for (int j = hunq; j >= tempNum; j--) {
                    dp[j] = Math.max(dp[j], dp[j - tempNum] + tempNum );
                }
            }
            double res = (double)(dp[hunq]/100.00);
            System.out.printf("%.2f\n" , res);
        }
    }
}
/**************************************************************
    Problem: 1025
    User: wangzhenqing
    Language: Java
    Result: Accepted
    Time:420 ms
    Memory:49096 kb
****************************************************************/

C++ AC

#include <stdio.h>
const int maxn = 32;
int n,i;
double q;
int numArr[32];
int max(int a, int b){
    return a > b ? a : b;
}
int main(){
    while(scanf("%lf %d",&q,&n) != EOF){
        if(n == 0){
            break;
        }
        int len = 0;
        while (n > 0) {
            double A = 0;
            double B = 0;
            double C = 0;
            double price;
            int valid = 0;
            char c;
            int m;
            scanf("%d",&m);
            while (m > 0) {
                getchar();
                scanf("%c:%lf", &c, &price);
                if (c == 'A') {
                    A += price;
                }else if (c == 'B') {
                    B += price;
                }else if (c == 'C') {
                    C += price;
                }else {
                    valid = 1;
                }
                m--;
            }  
            if (valid == 0 && A <= 600.00 && B <= 600.00 && C <= 600.00) {
                double total = A + B + C;
                if (total <= 1000.00 && total <= q) {
                    numArr[len] = (int)(total*100);
                    len++;
                }
            }
            n--;
        }
        int hunq = (int) (q * 100);
        int *dp = new int[hunq + 1];
        for(i = 0; i < hunq+1; i++){
            dp[i] = 0;
        }
        for (i = 0; i < len; i++) {
            int tempNum = numArr[i];
            for (int j = hunq; j >= tempNum; j--) {
                dp[j] = max(dp[j], dp[j - tempNum] + tempNum );
            }
        }
        double res = (double)(dp[hunq]/100.00);
        printf("%.2lf\n",res);
    }
    return 0;
}
/**************************************************************
    Problem: 1025
    User: wangzhenqing
    Language: C++
    Result: Accepted
    Time:30 ms
    Memory:21816 kb
****************************************************************/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: