01背包问题的变形
以发票张数作为背包容量,选出可以报销的发票进行动态规划
dp[i][j] = max(dp[i-1][j-1] + v[i], dp[i-1][j]);
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
double dp[35], v[35], q, u;
int f[35], n, m;
char ch;
int main()
{
while(scanf("%lf %d", &q, &n), n)
{ memset(dp, 0, sizeof(dp));
memset(f, 0, sizeof(f));
int ca = 0;
for(int i=1; i<=n; i++)
{
double a, b, c;
a = b = c = 0;
scanf("%d", &m);
while(m--)
{
scanf(" %c:%lf", &ch, &u);
if(ch == 'A')
a += u;
else if(ch == 'B')
b += u;
else if(ch == 'C')
c += u;
else
f[i] = 1;
}
if(!f[i] && a<=600 && b<=600 && c<=600 && a+b+c<=1000)
v[++ca] = a+b+c;
}
for(int i=1; i<=n; i++)
for(int j=i; j>=1; j--)
dp[j] = max(dp[j], dp[j-1] + v[i]);
for(int i=ca; i>=0; i--)
if(dp[i] <= q)
{
printf("%.2f\n", dp[i]);
break;
}
}
return 0;
}
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
double dp[35][35], v[35], q, u;
int f[35], n, m;
char ch;
int main()
{
while(scanf("%lf %d", &q, &n), n)
{
memset(dp, 0, sizeof(dp));
memset(f, 0, sizeof(f));
int ca = 0;
for(int i=1; i<=n; i++)
{
double a, b, c;
a = b = c = 0;
scanf("%d", &m);
while(m--)
{
scanf(" %c:%lf", &ch, &u);
if(ch == 'A')
a += u;
else if(ch == 'B')
b += u;
else if(ch == 'C')
c += u;
else
f[i] = 1;
}
if(!f[i] && a<=600 && b<=600 && c<=600 && a+b+c<=1000)
v[++ca] = a+b+c;
}
for(int i=1; i<=ca; i++)
for(int j=0; j<=i; j++)
dp[i][j] = max(dp[i-1][j-1]+v[i], dp[i-1][j]);
for(int i=ca; i>=0; i--)
if(dp[ca][i] <= q)
{
printf("%.2f\n", dp[ca][i]);
break;
}
}
return 0;
}