HDOJ 1864 最大报销额

来源:互联网 发布:mac视频剪辑工具 编辑:程序博客网 时间:2024/06/10 09:20

今天做的两道DP和我以前做的不同,以前没试过换个变量来当作背包的容量,前面一道题奠定了这题的基础,这道题一看见的时候就知道用支票的个数来当容量,这道题有点题意不清,没看discuss的时候我也把题意理解错了,它说单项物品不超过600元其实是此类物品不超过600元,这道题也不能完全按照Robberies来做,这里有金额q的限制.

转移方程为d[i]=max(d[j])+p[i]; 1=<j<i;

代码:

#include<iostream>#include<cmath>using namespace std;double dp[35],p[35];int main(){    int n,flag,i,j,m;    double q,sum,temp,d[100];    char ch;    while( scanf("%lf%d",&q,&n)&&n){           j=1;           for( i=1; i<=n; i++){                scanf("%d",&m);                 flag=1;                sum=0;                memset(d,0,sizeof(d));                while( m--){                       scanf(" %c:%lf",&ch,&temp);                       d[ch-'A']+=temp;   //是同类物品的累计                       if( ch!='A'&&ch!='B'&&ch!='C'||d[ch-'A']>600){                           flag=0;                       }                       sum+=temp;                }                if( sum<=1000&&flag)                    p[j++]=sum;           }           n=j-1;           memset(dp,0,sizeof(dp));           double ret=0;           for( i=1; i<=n; i++){                double mx=0.0;                for( j=1; j<i; j++)                     if( dp[j]>mx&&dp[j]+p[i]<=q)                         mx=dp[j];                dp[i]=mx+p[i];                if( ret<dp[i])                    ret=dp[i];           }           printf("%.2lf\n",ret);    }    return 0;}

  或者把最后的关键代码改成比较普通的0/1背包就比较好理解了。

 for( i=1; i<=n; i++){      for( j=n; j>0; j--){           temp=dp[j-1]+p[i];           if( temp<=q&&temp>dp[j])               dp[j]=temp;      } }