HDU 1864 01背包(小数扩大)

本文详细介绍了01背包问题的动态规划求解策略,并结合HDU 1864题目进行实例解析,探讨了在处理小数权重时的扩展方法。
摘要由CSDN通过智能技术生成
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;//#include<algorithm>using namespace std;为了调用库函数max

int dp[3000005];//最多三十张每张最多1000,因为小数点后两位再乘100

int main()
{
    double Q;
    int N;
    int i,j,k;
    while(scanf("%lf%d",&Q,&N)!=EOF)
    {   
        k=1;//新背包的下表
        if(N==0)
            return 0;
        int q=(int)(Q*100);//将小数化成整数,因为for循环中j必须为整数
        int sum[35];//去掉不符合报销规则后剩下的背包
        memset(sum,0,sizeof(sum));//养成好习惯
        for(i=1;i<=N;i++)
        {
            int m;
            scanf("%d",&m);
            int a[4]={0};//0不用设置三个数来分别存储A类B类C类的总额
            int flag=1;//1符合规则放进新背包数组,不符合去掉
            for(j=1;j<=m;j++)
            {
                char c;
                double temp;
                scanf(" %c:%lf",&c,&temp);//在输入中加入:注意题中所给是英文状态下":"
                int price=(int)(temp*100);//每件物品同样扩大100
                if(c=='A')
                    a[1]+=price;
                else if(c=='B')
                    a[2]+=price;
                else if(c=='C')
                    a[3]+=price;
                else
                {
                    flag=0;
                    break;
                }
                if(a[1]>60000||a[2]>60000||a[3]>60000)//某类型不符合去掉该发票
                {
                    flag=0;
                }
                if(a[1]+a[2]+a[3]>100000)//总额不符合,去掉该发票
                {
                    flag=0;
                }
            }
            if(flag)
            sum[k++]=a[1]+a[2]+a[3];//设置新背包
        }
        memset(dp,0,sizeof(dp));//注意设置
        dp[0]=0;//好习惯
        for(i=1;i<=k-1;i++)//k++比实际多1
            for(j=q;j>=sum[i];j--)
                dp[j]=max(dp[j],dp[j-sum[i]]+sum[i]);//该题目只给了钱的总数,所以sum[i]既是01背包中物品的价值,也是01背包的物品的体积
        printf("%.2lf\n",(double)dp[q]/100);//类型转换
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值