HDOJ 1864 最大报销额

今天做的两道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;
      }
 }


posted on 2012-07-19 21:04  java课程设计例子  阅读(228)  评论(0编辑  收藏  举报