1. 程式人生 > >01揹包-03 小P的故事——神奇的發票報銷

01揹包-03 小P的故事——神奇的發票報銷

小P的故事——神奇的發票報銷

Time Limit: 1000 ms Memory Limit: 65536 KiB

Submit Statistic

Problem Description

為響應黨的號召,小P所在的大學現在嚴格規範報銷制度,禁止鋪張浪費。特作如下規定:允許報銷的發票型別包括買圖書(A類)、文具(B類)、差旅(C類),要求每張發票的總額不得超過1000元,每張發票上,單項物品的價值不得超過600元。

現在老師決定把這報銷發票的重任交付於小P,給他一沓發票,讓他找出可以報銷的、不超過給定額度的最大報銷額。小P能成功完成組織交給他的任務嗎?顯然不能啊、、所以還得靠你啊、、、

Input

 測試輸入包含若干測試用例。

每個測試用例的第1行包含兩個正數 Q 和 N,其中 Q 是給定的報銷額度,N(<=30)是發票張數。隨後是 N 行輸入,每行的格式為:

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

其中正整數 m 是這張發票上所開物品的件數,Type_i 和 price_i 是第 i 項物品的種類和價值。

物品種類用一個大寫英文字母表示。

當N為0時,全部輸入結束,相應的結果不要輸出。

Output

 對每個測試用例輸出1行,即可以報銷的最大數額,精確到小數點後2位。

Sample Input

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

Sample Output

123.50 
1000.00 
1200.50

Hint

 

Source

xfl

 

#include <bits/stdc++.h>
using namespace std;
int dp[3000001], vi[33];
int main()
{
    double q, num, A, B, C;
    int n;
    char c;
    while (~scanf("%lf %d", &q, &n) && n)
    {
        int Q = q * 100; // 避免dp陣列出問題我們把錢數都乘100
        memset(dp, 0, sizeof(dp));
        memset(vi, 0, sizeof(vi));
        for (int m = 0; m < n; m++)
        {
            int sum, k, flag = 1;
            sum = A = B = C = 0;
            scanf("%d", &k);
            getchar(); // 收納行末回車
            for (int i = 0; i < k; i++)
            {
                scanf("%c:%lf", &c, &num);
                getchar();
                if (c == 'A')
                    A += num * 100;
                else if (c == 'B')
                    B += num * 100;
                else if (c == 'C')
                    C += num * 100;
                else // 不是ABC的情況
                    flag = 0;
            }
            sum = A + B + C;
            if (A > 60000 || B > 60000 || C > 60000)
                flag = 0;
            if (sum <= 100000 && flag)  // 當小於報銷金額且 沒有600的沒有不是ABC的時候
                vi[m] = sum;
            else
                vi[m] = 0;
        }

        /*01揹包部分*/
        for (int i = 0; i < n; i++)
        {
            for (int j = Q; j > 0; j--)
            {
                if (j >= vi[i])
                    dp[j] = max(dp[j], dp[j - vi[i]] + vi[i]);
            }
        }
        printf("%.2lf\n", dp[Q] / 100.0);
    }
    return 0;
}