这是一道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; }