[每日一题] 2019.3.25 P2736 “破锣摇滚”乐队 [动态规划]

P2736 “破锣摇滚”乐队

动态规划
第一版,递归:

#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]);
}

猜你喜欢

转载自blog.csdn.net/AdamAndTina/article/details/88791939