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

时间:2020-12-21 18:45:59

题目链接:HDU 1864 最大报销额

01背包。

把张数当成背包,状态转移方程:f[j]=max(f[j],f[j-1]+v[i]),f[j]表示把j张装进背包的最大报销额。

这题这么做还是有点问题,比如这组数据:

100.00 5
1 A:5
1 B:20
1 C:24
1 A:30
1 A:60

f[3]为114,f[2]为90,f[3]超过了100.00,那么就会输出f[2]=90,但是很明显这个题最大报销额是95。不过这么写在杭电也能过。我看有人用Q*100作为背包,虽然不会错了,但是因为Q*100太大了,可能会超内存。

#include <iostream>
#include <cstring>
#include<iomanip>

using namespace std;

const int MAX_N = 30 + 3;
double money[3],dp[MAX_N],value[MAX_N];
double _max;
int n;

int main()
{
    while(cin >> _max >> n,n)
    {
        int cnt = 0;
        for(int i = 0;i < n;i++)
        {
            int m;
            cin >> m;
            memset(money,0,sizeof(money));
            bool flag = true;
            char a,b;
            double v;
            for(int j = 0;j < m;j++)
            {
                cin >> a >> b >> v;
                if(a == 'A')
                    money[0] += v;
                else if(a == 'B')
                    money[1] += v;
                else if(a == 'C')
                    money[2] += v;
                else
                    flag = false;
            }
            if(flag)
            {
                if(money[0] + money[1] + money[2] <= min(1000.0,_max) && money[0] <= 600.0 && money[1] <= 600.0 && money[2] <= 600.0)
                    value[cnt++] = money[0] + money[1] + money[2];
            }
        }
        memset(dp,0,sizeof(dp));
        for(int i = 0;i < cnt;i++)
        {
            for(int j = cnt;j >= 1;j--)
            {
                dp[j] = max(dp[j],dp[j - 1] + value[i]);
            }
        }
        for(int i = cnt;i >= 0;i--)
        {
            if(dp[i] <= _max)
            {
                cout << fixed << setprecision(2) << dp[i] << endl;
                break;
            }
        }
    }
    return 0;
}