题意还是比较复杂的,限制比较多,需要先筛除不满足报销条件的发票:
1.出现 ABC之外的类不报销;2.一张发票内单个类超过600元不报销;3.发票的总金额超过1000不报销。
知道这三个条件之后筛除不满足的剩下的就是01背包了。
这里金额是double类,所以统一乘100,最后再除掉就好了(数据范围可以接受的情况下),把重量和价值看作一样,不过这样会很慢。 方程:dp[j] = max( dp[j] , dp[j-v[i]]+v[i] );
另一种优秀的做法的方程是:f[j]=max(f[j],f[j-1]+v[i]);
第一种:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
//#pragma comment(linker, "/STACK:1024000000,1024000000")
const int maxn = 3000000+10;
int dp[maxn];
double money;
double max_money;
int n;
int time;
int v[maxn];
char ch1,ch2;
int main()
{
while(cin >> max_money >> n)
{
if(n==0) break;
memset(v,0,sizeof(v));
memset(dp,0,sizeof(dp));
int E=0;
bool flag = true;
max_money *= 100;
int Max_money = max_money;
for(int k=0; k<n; k++)
{
cin >> time;
int sum = 0;
flag = true;
int a,b,c;
a=b=c=0;
for(int i=0; i<time; i++)
{
cin >> ch1 >> ch2;
cin >> money;
if(money>600) flag = false;
money *= 100;
int Money = money;
if(ch1=='A') a+=Money;
else if(ch1=='B') b+=Money;
else if(ch1=='C') c+=Money;
else flag = false;
if(a>60000||b>60000||c>60000) flag = false;
sum += Money;
if( sum>100000 ) flag = false;
}
// cout << "sum:" << sum << endl;
// cout << "flag" << flag <<endl;
if(flag)
{
v[E++] = sum;
//- cout << "sum: " << sum <<endl;
}
}
// cout << "EEE:" << E <<endl;
// for(int i=0;i<E;i++) cout << " " << v[i];
for(int i=0;i<E;i++)
{
for(int j=Max_money;j>=v[i];j--)
{
dp[j] = max( dp[j] , dp[j-v[i]]+v[i] );
}
}
printf("%.2lf\n",dp[Max_money]*1.0/100 );
}
return 0;
}
我山东