一道简单的动态规划

这是一道usaco的题,section 3.4 raucous rockets

如果只有1张唱片,就是一个背包问题,现在有m张唱片,怎么办呢?

dp[i][j][k]表示前i首歌曲在j个cd中最后一个cd时间为k的最大值

如果这首歌不选,就是dp[i-1][j][k]

如果选,可以在当前时间就选,就是dp[i-1][j][k-a[i]]+1

也可以在以前选啊。。就是dp[i][j][k-1](如果k是0怎么办?那就用dp[i][j-1][t(t是时间最大值)]!)

这里可以优化啊。。在现在的cd上又不马上放的话还不如在当前就选。。所以就相当于在前面的cd上放。那我们就用dp[i][j-1][t];

我们就得到了递推式dp[i][j][k] = max(dp[i-1][j][k],  dp[i-1][j][k-a[i]]+1,  dp[i][j][k-1]);

写出代码:

# include <cstdio>
# include <iostream>
# include <algorithm>
using namespace std;
int dp[21][21][21],a[21];
int main()
{
    freopen("rockers.in","r",stdin);
    freopen("rockers.out","w",stdout);
    int n,t,m,i,j,k;
    cin>>n>>t>>m;
    for (i=1;i<=n;++i)
        cin>>a[i];
    for (i=1;i<=n;++i)
        for (j=1;j<=m;++j)
            for (k=0;k<=t;++k)
            {
                if (k==0) 
                    dp[i][j][k] = max(dp[i][j-1][t],dp[i-1][j][k]);
                else
                    dp[i][j][k] = max(dp[i][j][k-1],dp[i-1][j][k]);
                if (k>=a[i]&&dp[i][j][k] < dp[i-1][j][k-a[i]]+1)
                    dp[i][j][k] = dp[i-1][j][k-a[i]]+1;
            }    
    cout<<dp[n][m][t]<<endl;
    return 0;
}

 还可以写

# include <cstdio>
# include <iostream>
# include <algorithm>
using namespace std;
int dp[21][21][21],a[21];
int main()
{
    freopen("rockers.in","r",stdin);
    freopen("rockers.out","w",stdout);
    int n,t,m,i,j,k;
    cin>>n>>t>>m;
    for (i=1;i<=n;++i)
        cin>>a[i];
    for (i=1;i<=n;++i)
        for (j=1;j<=m;++j)
            for (k=0;k<=t;++k)
            {
                   dp[i][j][k] = max(dp[i][j-1][t],dp[i-1][j][k]);
                if (k>=a[i]&&dp[i][j][k] < dp[i-1][j][k-a[i]]+1)
                    dp[i][j][k] = dp[i-1][j][k-a[i]]+1;
            }    
    cout<<dp[n][m][t]<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/1carus/p/3328919.html