这是一个典型的背包问题 让我们求学生Z在t天挂科数小于等于p的情况下借助总共给出的m份资料所得的最大分数总和
我们用 f[i][j] 来表示第i科花费j时间所得的最大分数
用 dp[i][j][k] 来表示前i门科目花费j时间挂科数为k的情况下所得的最大分数总和
求f 和 dp都是01背包 只不过一个是科目得分 一个是 f 作为价值
对于字符串我们可以用map转化为序号id 从而方便我们存数 再设一个vector来保存所有当前序号的价值和花费时间
1. f[i][j] 的修改
for (int i = 1; i <= n; i ++ )
{
f[i][0] = 0;
for (int j = 0; j < cour[i].size(); j ++ )
{
int val = cour[i][j].val, time = cour[i][j].time;
for (int k = t; k >= time; k -- )
f[i][k] = max(f[i][k], f[i][k - time] + val);
}
}
2. dp[i][j][k] 的修改
for (int i = 1; i <= n; i ++ )
{
for (int j = 0; j <= t; j ++ ) // 当前科目花费时间
for (int k = j; k <= t; k ++ ) // 总时间
for (int lim = 0; lim <= p; lim ++ ) // 挂科数
{
if (f[i][j] < 0) continue;
int flag = 0;
if (f[i][j] < 60) flag = 1;
if (f[i][j] > 100) f[i][j] = 100;
if (lim >= flag)
dp[i][k][lim] = max(dp[i][k][lim], dp[i - 1][k - j][lim - flag] + f[i][j]);
}
}
3. 总代码
#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII; // x-val y-time
const int N = 60, M = 3010;
int n, m, t, p;
int f[N][M], dp[N][M][10];
map<string, int> mp;
vector<PII> course[N];
int main()
{
int T;
scanf("%d", &T);
while (T -- )
{
scanf("%d", &n);
mp.clear();
for (int i = 1; i <= n; i ++ ) course[i].clear();
for (int i = 1; i <= n; i ++ )
{
string s;
cin >> s;
mp[s] = i;
}
scanf("%d", &m);
for (int i = 0; i < m; i ++ )
{
string s;
cin >> s;
int id = mp[s];
PII a;
cin >> a.x >> a.y;
course[id].push_back(a);
}
scanf("%d%d", &t, &p);
memset(f, -0x3f, sizeof f);
memset(dp, -0x3f, sizeof dp);
dp[0][0][0] = 0;
for (int i = 1; i <= n; i ++ )
{
f[i][0] = 0;
for (int j = 0; j < course[i].size(); j ++ )
{
int val = course[i][j].x, time = course[i][j].y;
for (int k = t; k >= time; k -- )
f[i][k] = max(f[i][k], f[i][k - time] + val);
}
for (int j = 0; j <= t; j ++ )
for (int k = j; k <= t; k ++ )
for (int lim = 0; lim <= p; lim ++ )
{
int flag = 0;
if (f[i][j] < 0) continue;
if (f[i][j] < 60) flag = 1;
if (f[i][j] > 100) f[i][j] = 100;
if (lim >= flag)
dp[i][k][lim] = max(dp[i][k][lim], dp[i - 1][k - j][lim - flag] + f[i][j]);
}
}
int ans = -1;
for (int i = 0; i <= t; i ++ )
for (int j = 0; j <= p; j ++ )
ans = max(ans, dp[n][i][j]);
if (ans < 0) puts("-1");
else printf("%d\n", ans);
}
return 0;
}