题目大意
有一个人要为了期末考试而复习,现在一共有 n n n 门课,给你每门课复习时间所对应的分数,现在你有 t t t 时间来复习,最多挂 p p p 门课,每门课最多得分100,问你在最多挂 p p p 门课的情况下最大得分是多少,否则输出 -1
解题思路
先用一个背包
f
[
i
]
[
j
]
f[i][j]
f[i][j] 表示第
i
i
i 门课花费时间
j
j
j 的最大得分是多少
然后进行一个
d
p
dp
dp
d
p
[
i
]
[
k
]
[
k
k
]
dp[i][k][kk]
dp[i][k][kk] 表示前
i
i
i 门课,花费时间
k
k
k,在挂
k
k
kk
kk 门的情况下,最大得分是多少。
当
f
[
i
]
[
j
]
≥
60
f[i][j] \geq 60
f[i][j]≥60 时
d
p
[
i
]
[
k
]
[
k
k
]
=
m
a
x
(
d
p
[
i
]
[
k
]
[
k
k
]
,
d
p
[
i
]
[
k
−
j
]
[
k
k
]
+
f
[
i
]
[
j
]
)
dp[i][k][kk] = max(dp[i][k][kk],dp[i][k-j][kk]+f[i][j])
dp[i][k][kk]=max(dp[i][k][kk],dp[i][k−j][kk]+f[i][j])
当
f
[
i
]
[
j
]
<
60
f[i][j] < 60
f[i][j]<60 时
d
p
[
i
]
[
k
]
[
k
k
]
=
m
a
x
(
d
p
[
i
]
[
k
]
[
k
k
]
,
d
p
[
i
]
[
k
−
j
]
[
k
k
−
1
]
+
f
[
i
]
[
j
]
)
dp[i][k][kk] = max(dp[i][k][kk],dp[i][k-j][kk-1]+f[i][j])
dp[i][k][kk]=max(dp[i][k][kk],dp[i][k−j][kk−1]+f[i][j])
时间复杂度为
O
(
n
×
t
2
×
q
)
O(n\times t^2 \times q)
O(n×t2×q)
Code
#include <bits/stdc++.h>
#define ll long long
#define qc ios::sync_with_stdio(false); cin.tie(0);cout.tie(0)
#define fi first
#define se second
#define PII pair<int, int>
#define PLL pair<ll, ll>
#define pb push_back
using namespace std;
const int MAXN = 5007;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 1e9 + 7;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
vector<PII> v[100];
map<string, int> mp;
int n, m, p, t;
int dp[100][507][4];
int f[57][507];
void solve(){
cin >> n;
mp.clear();
for(int i = 1; i <= n; i++){
string s;
cin >> s;
mp[s] = i;
v[i].clear();
}
memset(f, 0, sizeof f);
memset(dp, -0x3f, sizeof dp);
cin >> m;
while(m--){
string s;
int x, y;
cin >> s >> x >> y;
v[mp[s]].pb({x, y});
}
cin >> t >> p;
for(int i = 1; i <= n; ++i){
for(auto j : v[i]){
for(int k = t; k >= j.se; k--){
f[i][k] = max(f[i][k], f[i][k-j.se] + j.fi);
f[i][k] = min(100, f[i][k]);
}
}
}
dp[0][0][0] = 0;
for(int i = 1; i <= n; ++i){
for (int j = 0; j <= t; ++j){
for (int k = 0; k <= j; ++k){
for (int kk = 0; kk <= 3; ++kk){
if(f[i][k] >= 60) dp[i][j][kk] = max(dp[i][j][kk], dp[i-1][j-k][kk] + f[i][k]);
else if(kk) dp[i][j][kk] = max(dp[i][j][kk], dp[i-1][j-k][kk-1] + f[i][k]);
}
}
}
}
int ans = -1;
for (int i = 0; i <= p; ++i){
ans = max(ans, dp[n][t][i]);
}
cout << ans << "\n";
}
int main(){
#ifdef ONLINE_JUDGE
#else
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
qc;
int T;
cin >> T;
while(T--)
solve();
}