题意:求一个学生在最多挂P门课程的情况下,有T天时间让他复习课程,有n门课程,m本复习材料,问他能取得的最高分数是多少。
- 注意:没有满足条件的情况出现,要输出-1,没看到这句wa了好几发…
思路:
状态表示
f [ i ][ j ] 表示第 i 门课用 j 天复习能得到的最多分数
dp[ i ][ j ][ k ] 表示前 i 门课花 j 天挂 k 门的最多分数
f[ ] 数组使用背包维护
dp[ ][ ][ ]数组:需要枚举当前第 i 门课的学习天数 k状态转移
(当 f [ i ][ z ] < 60 ) dp[ i ][ j ][ k ] = max(dp[ i ][ j ][ k ], dp[ i - 1][ j - z ][ k - 1] + f[ i ][ z ])
( 当f [ i ][ k ] >= 60 ) dp[ i ][ j ][ k ] = max(dp[ i ][ j ][ k ], dp[ i - 1][ j - z][ k ] + f[ i ][ z ])
- 该题包含很多小细节需注意
accode:
#include<iostream>
#include<cstdio>
#include<cstring>
#include <string>
#include<algorithm>
#include<bitset>
#include<cassert>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<deque>
#include<iomanip>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
using namespace std;
map<string,int> s;
//f[i][j]:第i门课程花费j天能取得的最高分数
//dp[i][j][k]:在挂k门的情况下,i门课程复习j天的最高分数
int f[55][550];
int dp[55][550][5];
typedef pair<int,int> pll;
//map会对插入的元素按键自动排序,而且不允许键重复。
//vector<pair<int, int>>这种用法不会自动排序,而且允许重复。
inline int max(int a, int b){return (a > b) ? a : b;}
inline int min(int a, int b){return (a < b) ? a : b;}
int main()
{
ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
int t, n, m, x, y, T, P;
string str;
scanf("%d", &t);
while(t--)
{
s.clear();
vector<pll> q[55];
memset(f,-0x3f,sizeof f);
memset(dp,-0x3f,sizeof dp);
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
cin>>str;
s[str] = i;
}
scanf("%d", &m);
for(int i = 1; i <= m; i++)
{
cin>>str>>x>>y;
q[s[str]].push_back({x, y});
}
scanf("%d %d", &T, &P);
for(int i = 1; i <= n; i++) f[i][0] = 0;//初始化
for(int i = 1; i <= n; i++)
{
for(int j = 0; j < q[i].size(); j++)//注意从0开始
{
for(int k = T; k >= q[i][j].second; k--)//从大到小,花费k天复习材料
{//f[]数组用背包维护
f[i][k]=min(100,max(f[i][k],f[i][k-q[i][j].second]+q[i][j].first));
}
}
}
dp[0][0][0]=0;
//前三维对应 n, T, P
for(int i=1;i<=n;i++)//第几门课
{
for(int j=0;j<=T;j++)//学习天数
{
for(int k=0;k<=P;k++)//挂几门课
{
for(int z=0;z<=j;z++)//该课程学习天数
{
if(f[i][z]<60&&k!=0)//注意此处的 k != 0
dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-z][k-1]+f[i][z]);
else if(f[i][z]>=60)
dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-z][k]+f[i][z]);
}
}
}
}
int ans = -1;
for(int i = 0; i <= P; i++)
ans = max(ans, dp[n][T][i]);
cout<<ans<<endl;
}
return 0;
}