题意
n n n门课, m m m个课程与成绩与天数的关系,最多复习 T T T天,在挂科数量 ≤ P \le P ≤P的情况下的最大得分。
分析
状态表示
f
[
i
]
[
j
]
f[i][j]
f[i][j] 表示第
i
i
i门课用
j
j
j天复习能得到的最大分数
d
p
[
i
]
[
j
]
[
p
]
dp[i][j][p]
dp[i][j][p] 表示前
i
i
i门课花
j
j
j天挂
p
p
p门的最大得分
f
f
f数组使用背包维护
g
g
g数组:需要枚举当前第
i
i
i门课的学习天数
k
k
k
状态转移
(
f
[
i
]
[
k
]
<
60
)
(f[i][k]<60)
(f[i][k]<60)
d
p
[
i
]
[
j
]
[
p
]
=
m
a
x
(
d
p
[
i
]
[
j
]
[
p
]
,
d
p
[
i
−
1
]
[
j
−
k
]
[
p
−
1
]
+
f
[
i
]
[
k
]
)
dp[i][j][p]=max(dp[i][j][p], dp[i-1][j-k][p-1]+f[i][k])
dp[i][j][p]=max(dp[i][j][p],dp[i−1][j−k][p−1]+f[i][k])
(
f
[
i
]
[
k
]
≥
60
)
(f[i][k]\ge 60)
(f[i][k]≥60)
d
p
[
i
]
[
j
]
[
p
]
=
m
a
x
(
d
p
[
i
]
[
j
]
[
p
]
,
d
p
[
i
−
1
]
[
j
−
k
]
[
p
]
+
f
[
i
]
[
k
]
)
dp[i][j][p]=max(dp[i][j][p], dp[i-1][j-k][p]+f[i][k])
dp[i][j][p]=max(dp[i][j][p],dp[i−1][j−k][p]+f[i][k])
代码
#include <iostream>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <iomanip>
#include <map>
#include <cstdio>
#include <stack>
#include <set>
using namespace std;
typedef long long ll;
typedef pair<int ,int > pii;
#define endl '\n'
ll gcd(ll a, ll b){
return b == 0 ? a : gcd(b, a % b);
}
void input(){
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
}
inline int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*f;
}
const int N = 1e6+10, M = N * 2, inf = 1e8;
const int maxke = 60, maxt = 510, maxgua = 4;
int f[maxke][maxt]; // 第i门课花j天最大得分
int dp[maxke][maxt][maxgua]; // 前i门课花j天挂p门最大得分
map<string, int> mp;
vector<pii> a[maxke]; // {得分,天数}
int t, n, m;
int T, P;
void init(){
mp.clear();
memset(f, -0x3f, sizeof(f));
memset(dp, -0x3f, sizeof(dp));
for(int i = 0; i < maxke; i++) a[i].clear();
}
int main(){
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
//input();
cin>>t;
while(t--){
init();
cin>>n;
int id = 1;
for(int i = 1; i <= n; i++){
string s; cin>>s; mp[s] = id++;
}
cin>>m;
for(int i = 1; i <= m; i++){
string s; int a1, b; cin>>s>>a1>>b;
a[mp[s]].push_back(make_pair(a1, b));
}
cin>>T>>P;
for(int i = 0; i <= n; i++) f[i][0] = 0;
for(int x = 1; x <= n; x++)
for(int i = 0; i < a[x].size(); i++)
for(int j = T; j >= a[x][i].second; j--)
f[x][j] = min(100, max(f[x][j],f[x][j-a[x][i].second]+a[x][i].first));
dp[0][0][0] = 0;
for(int i = 1; i <= n; i++) // i门课
for(int j = 0; j <= T; j++) // 天数
for(int p = 0; p <= P; p++) // 挂几门
for(int k = 0; k <= j; k++) // 当前课几天学
if(f[i][k] < 60 && p != 0) dp[i][j][p] = max(dp[i][j][p], dp[i-1][j-k][p-1] + f[i][k]);
else if(f[i][k] >= 60) dp[i][j][p] = max(dp[i][j][p], dp[i-1][j-k][p] + f[i][k]);
int ans = -1;
for(int p = 0; p <= P; p++) ans = max(ans, dp[n][T][p]);
cout<<ans<<endl;
}
return 0;
}
比赛时没想到思路,还是队友给力。。。要多练练了。