1. 程式人生 > >hdu 1864 01背包

hdu 1864 01背包

!= include scan 我們 target getc using AS 接受

題目鏈接: 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 ; }

hdu 1864 01背包