H . I love exam(dp)

题目:

I love exam HDU - 6968

Student Z doesn't love exams

The exam was about to be done soon, but student Z didn't even read the book, He had collapsed.

Student Z has a total of nn exams, and there are still t days before the start of the exam, which means he still has t days to PREVIEW.

But student Z couldn’t even read the textbooks, and couldn’t review it at all. Fortunately, a kind classmate gave him mm sets of review materials. The i set of materials can improve the grades of the sisi course. The i set of materials needs to be studied for yi days. You can increase xixi points later (the upper limit of each course is 100 points, so after it is upgraded to 100 points, there will be no further increase).and note that each set of review materials can only be used once.

Student Z now has a zero-point level in every course. it is impossible to review all the materials, so he needs to choose some materials to review, but he can fail at most p courses in this semester (if the score of one course is less than 60 points will fail), otherwise he will be talked to by the professor.

Student Z now wants to know the maximum points he can get in all courses under the premise of fail no more than p courses this semester. If he cannot meet the conditions, please output −1 .

Input

A positive integer T(T10) in the first line represents the number of test cases. For each test case:

  • The first line contains a positive integer n (n50) represents the total number of courses in this semester.
  • The second line contains nn strings which length is no more than 15, representing the course name of each course in this semester.
  • The third line contains a positive integer mm (m15000) represents the number of review materials he obtained.
  • In the next mm lines, each line have a string s and two positive integers x(1x10) and y(1y10) , representing the course of this set of materials review, the improved scores and The number of days required for learning(data assurance this course was studied this semester ).
  • The last line has two integers t,pt,p(1t5000p3) represents the number of review days that student Z has and the upper limit of the number of failed courses in this semester.

Output

For each test case, output a line with a positive integer representing the maximum score that student Z can obtain in the case of meeting the conditions .If he must be talked to by the professor, output −1。

题目大意:

有n个考试科目,现在有m套复习资料,每套复习资料需要花费wi天使用,用完提升ci的分数,现在还有t天复习时间,挂科数目不能超过p,问所有达到的最大分数

题解:

01背包
有两个背包转移过程
首先不用考虑挂科的事,我们将试题按照名称排序,对于每套试题进行转移,f[i]表示当前种类的试题,做题天数不超过i的最大分数
然后我们开始考虑挂科的事,dp[i][j][k]:前i种习题,一共学了j套 ,不及格k个科目的最大分数是多少 ?
转移方程为:
num表示当前为第num种习题
dp[num][k][lim]=max(dp[num-1][k-j][lim-x]+f[j],dp[num][k][lim]);

看他是不是挂科,主要看f[j]是否大于60,上式中k为学完这一科目的分数,枚举一下j,所以[k-j]就是上一科目的分数

代码:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=4000;
struct node{
    string a;
    int w,c;
}save[2200000];
int f[maxn];
int n;
int dp[100][maxn][5];
bool cmp(node x,node y){
    return x.a>y.a;
}
int main(){
    int t;
    cin>>t;
    while(t--){
        memset(dp,-0x3f,sizeof(dp)); 
        cin>>n;
        string s;
        for(int i=1;i<=n;i++){
            cin>>s;
        }
        int m;
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            cin>>save[i].a>>save[i].w>>save[i].c;
        }
        sort(save+1,save+m+1,cmp);
        int t,p;
        cin>>t>>p;
        int num=0;
        dp[0][0][0]=0;
        for(int x=1;x<=m;x++){
            int R=x;
            while(save[R].a==save[R+1].a&&R<=m){
                R++;
            } 
            num++;
            memset(f,-0x3f3f3f3f,sizeof(f));
            f[0]=0;
            for(int i=x;i<=R;i++){
                for(int j=t;j>=save[i].c;j--){
                    f[j]=max(f[j],f[j-save[i].c]+save[i].w);
                } 
            } 
            for(int i=1;i<=t;i++){//当前这个贡献了多少 
                for(int j=i;j<=t;j++){//上一个就是j-i 
                    for(int l=0;l<=p;l++){
                        if(f[i]<0){
                            continue;
                        }
                        int p=0;
                        if(f[i]<60) p=1;
                        if(f[i]>100) f[i]=100;
                        if(l>=p){
                            dp[num][j][l]=max(dp[num-1][j-i][l-p]+f[i],dp[num][j][l]);
                        }
                    } 
                }
            }
            x=R; 
        }
        int ans=-0x3f;
        for(int i=0;i<=t;i++){
            for(int j=0;j<=p;j++){
                ans=max(ans,dp[num][i][j]);
            }
        }
        if(ans<0){
            cout<<-1<<endl;
        }
        else{
            cout<<ans<<endl;
        }
    }
    return 0;
}

 

posted @ 2021-07-25 16:31  lipu123  阅读(80)  评论(0)    收藏  举报