HDU1864(01背包)

题意还是比较复杂的,限制比较多,需要先筛除不满足报销条件的发票:

1.出现 ABC之外的类不报销;2.一张发票内单个类超过600元不报销;3.发票的总金额超过1000不报销。

知道这三个条件之后筛除不满足的剩下的就是01背包了。

这里金额是double类,所以统一乘100,最后再除掉就好了(数据范围可以接受的情况下),把重量和价值看作一样,不过这样会很慢。 方程:dp[j] = max( dp[j] , dp[j-v[i]]+v[i] );

另一种优秀的做法的方程是:f[j]=max(f[j],f[j-1]+v[i]);

第一种:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>

using namespace std;
//#pragma comment(linker, "/STACK:1024000000,1024000000")
const int maxn = 3000000+10;
int dp[maxn];
double money;
double max_money;
int n;
int time;
int v[maxn];
char ch1,ch2;
int main()
{

    while(cin >> max_money >> n)
    {
        if(n==0) break;
        memset(v,0,sizeof(v));
        memset(dp,0,sizeof(dp));
        int E=0;
        bool flag = true;
        max_money *= 100;
        int Max_money = max_money;
        for(int k=0; k<n; k++)
        {
            cin >> time;
            int sum = 0;
            flag = true;
            int a,b,c;
            a=b=c=0;
            for(int i=0; i<time; i++)
            {
                cin >> ch1 >> ch2;
                cin >> money;

                if(money>600) flag = false;
                money *= 100;
                int Money = money;
                if(ch1=='A') a+=Money;
                else if(ch1=='B') b+=Money;
                else if(ch1=='C') c+=Money;
                else flag = false;
                if(a>60000||b>60000||c>60000) flag = false;
                sum += Money;
                if( sum>100000 ) flag = false;
            }
//            cout << "sum:" << sum << endl;
//            cout << "flag" << flag <<endl;
            if(flag)
            {
                v[E++] = sum;
               //- cout << "sum: " <<  sum <<endl;
            }
        }
//        cout << "EEE:" <<  E <<endl;
//        for(int i=0;i<E;i++) cout <<   "  " << v[i];
        for(int i=0;i<E;i++)
        {
            for(int j=Max_money;j>=v[i];j--)
            {
                dp[j] = max( dp[j] , dp[j-v[i]]+v[i] );
            }
        }
        printf("%.2lf\n",dp[Max_money]*1.0/100 );
    }
    return 0;
}



  我山东

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值