这个题是 在 n 张 发票里面 选出满足题意的不超过 给定额度的 最大的发票钱数。
明显的0 1背包。 也就是说。 对于 每一张发票 选择 或者不选。 但是自己对 0 1背包忘得差不多了。。
那么 我们可以用 f【i】 来表示 前 i 张发票的最大钱数。 则 f【i】 = max(f【i】,f【j】 + money【i】)
输入处理比较麻烦一点。 必须种类是 A B C 并且 每一类的 价钱不能超过 600 发票总额 不能超过 1000
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <fstream>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <list>
#include <vector>
#include <cmath>
#include <iomanip>
typedef long long LL;
typedef unsigned long long LLU;
const double PI=acos(-1.0);
using namespace std;
#define MAXN 100+10
int main (){
double M;
int n;
while(scanf("%lf%d",&M,&n) && n){
vector <double> _sum; // 每张发票的钱数
_sum.push_back(0);
for(int i = 0; i < n; i++){
int num;
scanf("%d",&num);
char c;
double sum = 0;
double mo;
int flag = 1;
double s[30]={0};
for(int j = 0; j < num ; j++){
scanf(" %c:%lf",&c,&mo);
s[c-'A'] += mo;
if(c != 'A' && c != 'B' && c != 'C')
flag = 0;
sum += mo;
}
for(int i = 0; i < 3; i++){
if(s[i] > 600)
flag = 0;
}
if(sum > 1000)
flag = 0;
if(flag)
_sum.push_back(sum);
}
double f[MAXN] = {0};
for(int i = 1; i <= _sum.size(); i++){ // 代表的是 第几张发票
for(int j = 1; j <= i; j++){
if(f[j] + _sum[i] <= M){
f[i] = max(f[i],f[j]+_sum[i]); // 代表前几张发票
}
}
}
printf("%.2lf\n",f[_sum.size()]);
}
return 0;
}