动态规划
第一版,递归:
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 21;
const int MAXM = 21;
const int MAXT = 21;
int n, t, m;// N首歌。M张CD。每张CD有T分钟
int time[MAXN]; // 每首歌的时间长度
int d[MAXM][MAXN][MAXT]; // 在还剩下i张CD,j首歌,第i张CD还剩t分钟的情况下最多可以塞多少首歌
bool vis[MAXM][MAXN][MAXT]; // 记录是否拜访过
void read () {
scanf("%d %d %d", &n, &t, &m);
for (int i = 0; i < n; i++) {
scanf("%d", &time[i]);
}
}
/*
* 参数:i是第几张唱片, j是已经排到几张歌了, k是剩余的时间
* 返回: 可以塞进几首歌
*/
int dp (int i, int j, int k) {
if (i == m || j == n) return 0;
if (!vis[i][j][k]) {
int &ans = d[i][j][k];
if (time[j] <= k) ans = 1 + dp(i, j+1, k-time[j]); // 这是将第j首歌塞到第i张唱片
else if (i < m-1 && time[j] <= t) ans = 1 + dp(i+1, j+1, t-time[j]); // 这是将第j首歌塞到新的唱片,要保证还有新的唱片可以塞以及塞得进
ans = max(ans, dp(i, j+1, k)); // 这是不塞歌
}
return d[i][j][k];
}
int main () {
read();
dp(0, 0, t);
printf("%d", d[0][0][t]);
return 0;
}
第二版,非递归
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAX = 21;
int n, t, m;// N首歌。M张CD。每张CD有T分钟
int time[MAX]; // 每首歌的时间长度
int d[MAX][MAX][MAX]; // 在还剩下i张CD,第i张CD还剩t分钟的情况下最多可以塞多少首歌
void read () {
scanf("%d %d %d", &n, &t, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", &time[i]);
}
}
int main () {
read();
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= t; j++) {
d[0][i][j] = 0;
}
}
for (int i = 1; i <= n; i++) { // 将第i首歌塞进去
for (int j = 1; j <= m; j++) { // 尝试塞到第j张CD
for (int k = 1; k <= t; k++) { // 第j张CD还剩k分钟
d[i][j][k] = d[i-1][j][k]; // 不塞入专辑
if (j > 1 && time[i] <= k && time[i] <= t) d[i][j][k] = max(d[i][j][k], d[i-1][j-1][t]+1); // 塞入一张新的CD
if (k >= time[i]) d[i][j][k] = max(d[i][j][k], d[i-1][j][k-time[i]]+1); // 塞入到旧的CD
}
}
}
printf("%d", d[n][m][t]);
}