HDU-6968(DP,和DP)

随便水一篇。(其实是多校单人A的机会太少了)

朱同学非常地不喜欢学习要考试了都没预习完。此时有若干个复习资料,对于一套资料而言,只需花费\(x\)天就能使该门课提升\(y\)分。(我也想要这种好东西)问能否在\(t\)天之内完成逆袭使得挂科数小于\(p\),如果能够创造奇迹,输出能获得的最大分数。

首先需要处理\(m\)份的复习资料,用DP来实现,用\(f[i][j]\)表示第\(i\)门课得到\(j\)分数所需要的最短天数,这一部分状态转移方程较为常见,复杂度为\(O(m*100)\)。

随后处理最大分数以及挂科数是否能够小于目标值。仍然用DP来实现,代码中用\(dp[i][j][k]\)表示\(i-1\)门课时花费\(j\)天且挂科数为\(k\)时能达到的最高分数。状态转移方程为\(dp[i+1][j+f[i][l]][k+1]=max(dp[i+1][j+f[i][l]][k+1],dp[i][j][k]+l)\)。\(l\)表示第\(i\)门课获得\(l\)分。这一部分做一个四重循环进行DP,但由于系数较小(50*500*4*100),时间复杂度是没有问题的。

#include<bits/stdc++.h>
#define fast ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
#define ll long long
#define pb push_back
using namespace std;
const int maxn = 60;
const int maxm = 15010;
string c[maxn];
int f[maxn][110];
map<string,int> mp;
int dp[maxn][510][4];
int main()
{
    fast;
    int T;
    cin>>T;
    while(T--)
    {
        mp.clear();
        int n,m;
        string s;
        int x,y;
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>c[i];
            mp[c[i]]=i;
            for(int j=0;j<=100;j++)
            {
                if(j==0) f[i][j]=0;
                else f[i][j]=-1;
            }
        }
        cin>>m;
        for(int i=1;i<=m;i++)
        {
            cin>>s>>x>>y;
            int tmp=mp[s];
            for(int j=100;j>=0;j--)
            {
                if(f[tmp][j]!=-1)
                {
                    if(f[tmp][min(j+x,100)]==-1) f[tmp][min(j+x,100)] = f[tmp][j]+y;
                    else f[tmp][min(j+x,100)] = min(f[tmp][min(j+x,100)],f[tmp][j]+y);
                }
            }
        }
        int day,limit;
        cin>>day>>limit;
        int minn=1e9;
        int maxx=-1;
        int sum=0;
        int flag=0;
        for(int i=0;i<=n+1;i++)
        {
            for(int j=0;j<=day;j++)
            {
                for(int k=0;k<=limit;k++)
                {
                    dp[i][j][k]=-1;
                }
            }
        }
        dp[1][0][0]=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<=day;j++)
            {
                for(int k=0;k<=3;k++)
                {
                    // if(k!=3) dp[i+1][j][k+1]=max(dp[i+1][j][k+1],dp[i][j][k]);
                    for(int l=0;l<=100;l++)
                    {
                        if(j+f[i][l]<=day && f[i][l]!=-1 && dp[i][j][k]!=-1)
                        {
                            if(l>=60) dp[i+1][j+f[i][l]][k]=max(dp[i+1][j+f[i][l]][k],dp[i][j][k]+l);
                            else
                            {
                                if(k!=3) dp[i+1][j+f[i][l]][k+1]=max(dp[i+1][j+f[i][l]][k+1],dp[i][j][k]+l);
                            }
                        }
                    }
                }
            }
        }
        /*for(int i=2;i<=n+1;i++)
        {
            for(int j=0;j<=day;j++)
            {
                for(int k=0;k<=limit;k++)
                {
                    cout<<i<<‘ ‘<<j<<‘ ‘<<k<<‘ ‘<<dp[i][j][k]<<‘\n‘;
                }
            }
        }*/
        for(int i=0;i<=day;i++)
        {
            for(int j=0;j<=limit;j++)
            {
                maxx=max(dp[n+1][i][j],maxx);
            }
        }
        if(maxx!=-1) cout<<maxx<<\n;
        else cout<<"-1\n";
    }
}

 

HDU-6968(DP,和DP)

上一篇:leetcode 合并两个有序链表 简单


下一篇:LinkedList与ArrayList的区别及LinkedList源码分析