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

来源:互联网 发布:人民币大写转换器软件 编辑:程序博客网 时间:2024/05/07 15:00

题目地址:点击打开链接

思路:01背包 ,只有ABC类能报销,有别的种类也不能报销,单类的物品不能超过600,超过也不能报销,扩大100倍算的,直接小数有点麻烦,主要思想是Tianyi Cui大神写的背包九讲,本博客算法精讲类有,写一下我认为最难的吧,就是用一维数组做01背包,背包的容量是从大到小循环的,之所以这样做就是不会产生覆盖问题,因为大的背包要用上一个阶段的小的背包的数据,如果先算小容量,后面大容量使用的数据就不是上一个阶段的数据了,会导致出错,因为可能会导致相同物品放多个进去,而用一维数组做完全背包,背包的容量是从小到大循环的,因为每个物品可以放无数个,所以不会产生错误。

AC代码:

#include<stdio.h>#include<string.h>int visit[40];int dp[3000100],cost[40];int max(int a,int b){return (a > b) ? a : b;}int main(){char l;int n,i,j,m,len,sum2,money,flag;int a,b,c;double q,sum1;while(scanf("%lf%d",&q,&n) && n){money = (int)(q * 100);len = 0;memset(visit,0,sizeof(visit));//只能初始化为0,-1,true,false,不能初始化为1memset(dp,0,sizeof(dp));for(i=0; i<n; i++){scanf("%d",&m);a = b = c = 0;flag = 1;for(j=0; j<m; j++){scanf(" %c:%lf",&l,&sum1);//前面一个空格;sum2 = (int)(sum1 * 100);if(l == 'A')a += sum2;else if(l == 'B')b += sum2;else if(l == 'C')c += sum2;elseflag = 0;}if(a + b + c <= 100000 && a <= 60000 && b <= 60000 && c <= 60000 && flag){cost[len++] = a + b + c;}}for(i=0; i<len; i++)//依次判断每件物品取舍的状况{for(j=money; j>=cost[i]; j--)//倒序是要防止产生覆盖问题,不然会造成后面大值用小值时候,小值已经改变{dp[j] = max(dp[j],dp[j-cost[i]] + cost[i]);}}printf("%.2lf\n",dp[money] / 100.0);}return 0;}


0 0
原创粉丝点击