返回顶部

【2021杭电多校第二场】 2021“MINIEYE杯”中国大学生算法设计超级联赛(2) I love exam (背包dp好题)

  • 题意:有\(n\)门课需要复习,每门课有\(m\)本资料,花费\(y\)时间可以是这门课得到\(x\)分,60分及格,剩下\(t\)时间,假设所有课现在不看资料去考试都是\(0\)分,问你在最多挂\(p\)门的情况下,总分最多能有多少,或者最少挂不止\(p\)门,输出\(-1\).

  • 题解:对于每门课,先背包求出花费时间能得到的最多分数,然后设\(dp[i][j][g]\)表示,前\(i\)门课花费\(j\)时间挂\(g\)门最多能得多少分,分挂还是没挂再背包转移一下即可。

  • 代码

    #include <bits/stdc++.h>
    #define ll long long
    #define fi first
    #define se second
    #define pb push_back
    #define me memset
    #define rep(a,b,c) for(int a=b;a<=c;++a)
    #define per(a,b,c) for(int a=b;a>=c;--a)
    const int N = 1e6 + 10;
    const int mod = 1e9 + 7;
    const int INF = 0x3f3f3f3f;
    using namespace std;
    typedef pair<int,int> PII;
    typedef pair<ll,ll> PLL;
    ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
    ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
    
    int n,m;
    string s;
    struct node{
        int fi,se;
    };
    vector<node> a[500];
    int x,y;
    int t,p;
    int f[2000];
    int dp[55][1000][20];
    map<string,int> mp;
    
    int main() {
        ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
        int _;
        cin>>_;
        while(_--){
            cin>>n;
            rep(i,1,n){
                cin>>s;
                mp[s]=i;
            }
            cin>>m;
            rep(i,1,m){
                cin>>s;
                cin>>x>>y;
                a[mp[s]].pb({x,y});
            }
            cin>>t>>p;
            me(dp,-0x3f,sizeof(dp));
            dp[0][0][0]=0;
            for(int i=1;i<=n;++i){
                me(f,-INF,sizeof(f));
                f[0]=0;
                for(int k=0;k<(int)a[i].size();++k){
                    for(int j=t;j>=a[i][k].se;--j){
                        f[j]=max(f[j],f[j-a[i][k].se]+a[i][k].fi);
                        f[j]=min(100,f[j]);
                    }
                }
                for(int l=1;l<=t;++l){
                    for(int j=l;j<=t;++j){
                        for(int g=0;g<=p;++g){
                            if(f[l]<0) continue;
                            if(f[l]<60){
                                if(g) dp[i][j][g]=max(dp[i][j][g],dp[i-1][j-l][g-1]+f[l]);
                            }
                            else dp[i][j][g]=max(dp[i][j][g],dp[i-1][j-l][g]+f[l]);
                        }
                    }
                }
            }
            int ans=-INF;
            for(int j=0;j<=t;++j){
                for(int g=0;g<=p;++g){
                    ans=max(ans,dp[n][j][g]);
                }
            }
            if(ans<0) cout<<-1<<'\n';
            else cout<<ans<<'\n';
            mp.clear();
            for(int i=1;i<=n;++i) a[i].clear();
        }
    
    
        return 0;
    }
    
posted @ 2021-07-25 16:59  Rayotaku  阅读(214)  评论(0编辑  收藏  举报