hdu 1864 01背包

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1864

解题思路:首先这题一看就是01背包,那么要思考的就是用什么作为背包容量,这里报销价格是浮点数,所以我们最好选择发票张数来作为背包的容量。这样数组也非常小,因为最多才30张

     那么状态转移方程就是  dp[j] = max (dp[j],dp[j-1]+price);  那么很明显报销张数越多报销金额越大,发票张数从大到小循环,直到遇到满足条件的报销金额,那么它就是答案。
     这题有些坑,首先每张发票上,同类商品价值和不能超过600,还有除A、B、C 三类商品外,含有其他品种该发票也作废。我是先用gechar() 处理掉字符,再接受浮点数。

 

AC代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
#define MAX 33
using namespace std;

double dp[MAX];

int main ()
{

   int n;
   char ch1;
   double p = 0;//允许报销的最大金额
   double price = 0;
   double p_a = 0;//分别对应a.b.c三类物品的总价值
   double p_b = 0;
   double p_c = 0;

  while(scanf("%lf%d",&p,&n)== 2 && n)
  {
    int m = 0 ;
    memset (dp,0,sizeof(dp));
   for (int i=0;i<n;++i)
    {
      scanf("%d",&m);
      price = 0;
      int flag = 1;//标记该发票是否具有报销资格。1表示有
      p_a = p_b =p_c = 0;
     for (int j = 0;j<m;++j)
     {
        double t_p;
        int  p_ch = 0;
      while( ( ch1 = getchar() ) !=':')//对字符的处理
        {
          if(ch1 =='A') p_ch = 1;
          if (ch1 == 'B') p_ch = 2;
          if (ch1 == 'C') p_ch = 3;  
        }
 
      scanf ("%lf",&t_p);
      if (p_ch == 0) flag = 0;//作废的票
      if (p_ch == 1) p_a +=t_p;  
      if (p_ch == 2) p_b +=t_p;  
      if (p_ch == 3) p_c +=t_p;
       
      if (p_a > 600 || p_b > 600 || p_c >600) flag = 0;
      price += t_p; //记录整张发票的总额
     }
        if (price > 1000   || !flag) continue;
       for (int j = n;j>= 1;--j)
        dp[j] = max (dp[j],dp[j-1]+price);
  }
   double ans = 0;
   for (int i =n;i>=0;--i)
    if (dp[i] <= p) {ans = dp[i];break;}

    printf ("%.2lf\n",ans);
   }
return 0 ;
}

 

posted @ 2018-04-21 12:44  雨落洛  阅读(167)  评论(0编辑  收藏  举报