GDUT_专题二:E - CD

news/2024/6/16 17:24:56 标签: 动态规划, 算法

题目:

你前面有很长的车程。你有一台录音机,但不幸的是,你最好的音乐是在 CD 上。你需要把它放在磁带上,所以要解决的问题是:你有一个 N 分钟长的磁带。如何从 CD 中选择曲目以充分利用磁带空间并尽可能减少未使用的空间。

假设:

• CD 上的曲目数不超过 20

• 曲目不超过 N 分钟

• 曲目不重复

• 每个音轨的长度以整数表示

• N 也是整数 程序应该找到最能填满磁带的轨道集,并以与轨道存储在 CD 上相同的顺序打印它

输入:

n<=10000,m<=20;

任意数量的行。每一个都包含值 N,(在空格之后)轨道数和轨道持续时间。例如,从样本数据的第一行开始:N = 5,曲目数=3,第一首曲目持续 1 分钟,第二首曲目持续 3 分钟,下一个曲目持续 4 分钟

输出:

一组轨道(和持续时间),它们是正确的解决方案和字符串“sum:”和持续时间的总和。

Sample Input

5 3 1 3 4
10 4 9 8 4 2
20 4 10 5 7 4
90 8 10 23 1 2 3 4 5 7
45 8 4 10 44 43 12 9 8 2

Sample Output
1 4 sum:5
8 2 sum:10
10 5 4 sum:19
10 23 1 2 3 4 5 7 sum:55
4 10 12 9 8 2 sum:45

思路分析:

对于sum的求和,从简单的01背包考虑很容易就能得到状态转移方程:dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - s[i]] + s[i]);问题在于如何求具体转移的方案,所以我们可以考虑再新建一个数组m记录每次转移所选取的方案,由于我们是顺序记录每次转移的方案,所以我们需要逆序遍历转移的状态才能找到正确的选取的方案。最后我们又需要输出正序的选择的方案,所以我们需要再次逆序输出记录的方案,对此我们可以借助栈的形式,先入栈再出栈就能得到具体的选取方案。对于背包问题具体方案的输出可以参考以下思路。具体解释可见代码注释。

代码:

二维数组的形式:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int s[25];
int dp[10010][10010];
int m[100][1010];
int main() {
	int n, num;
	while (~scanf("%d%d", &n, &num)) {
		for (int i = 1; i <= num; i++)cin >> s[i];
		memset(dp, 0, sizeof(dp));
		memset(m, 0, sizeof(m));
		for (int i = 1; i <= num; i++) { //个数
			for (int j = 0; j <= n; j++) { //空间
				if (j - s[i] >= 0) {//如果空间足够选取s[i]取选或不选的最大值 
					dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - s[i]] + s[i]);
					m[i][j] = 1;//并记录空间为j时的这个状态 
				} else {
					dp[i][j] = dp[i - 1][j];
				}
			}
		}
		int v[1100], top = 0;//v为用数组模拟栈,top为栈顶的指针 
		for (int i = num, j = n; i > 0 && j > 0 ; i--) {//因为dp时是顺序记录的状态,所以我们需要逆序推导一次转移过程 
			if (m[i][j]) {//如果该状态被记录过 
				v[++top] = s[i];//将该方案存入栈中 
				j -= s[i];//空间转移至下一个状态 
			}
		}
		while (top) {//所有数据出栈完成逆序输出 
			cout << v[top--] << ' ';
		}
		cout << "sum:" << dp[num][n] << endl;
	}
return 0;
}

对于dp压维减少空间复杂度的做法:

思路与二维思路一致,因为每次dp[i]的转移都有dp[i-1]有关,所以可以直接压维减少数组维度,但是要注意压维后空间由大到小遍历。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int s[25];
int dp[100000];
int m[100][10000];
int main() {
	int n, num;
	while (~scanf("%d%d", &n, &num)) {
		for (int i = 1; i <= num; i++)cin >> s[i];
		memset(dp, 0, sizeof(dp));
		memset(m, 0, sizeof(m));
		for (int i = 1; i <= num; i++) {
			for (int j = n; j >= s[i]; j--) {
				if (dp[j] < dp[j - s[i]] + s[i]) {
					dp[j] = dp[j - s[i]] + s[i];
					m[i][j] = 1;
				} else m[i][j] = 0;
			}
		}
		int v[1100], top = 0;
		for (int i = num, j = n; i > 0 && j > 0 ; i--) {
			if (m[i][j]) {
				v[++top] = s[i];
				j -= s[i];
			}
		}
		while (top) {
			cout << v[top--] << ' ';
		}
		printf("sum:%d\n", dp[n]);
	}
return 0;
}


http://www.niftyadmin.cn/n/633112.html

相关文章

MySQL一对一:一对多:多对多

学生表和课程表可以多对多 一个学生可以学多门课程 一门课程可以有多个学生: 多对多 *** 一个学生对应一个班级 一个班级对应多个学生: 一对多 *** 一个老师对应多个学生 多个学生对应一个老师:一对多 *** 一个老师教一门课 一门课对应一个老师: 一对一 1. 一对多(foreign key)…

论文解读 | network in network

借鉴了很多别的东西 找不到出处了 引用 Lin M, Chen Q, Yan S. Network In Network[J]. Computer Science, 2013. 目录 前言 创新点一&#xff1a;mlpconv mlpconv 的细节&#xff1a; 创新点二&#xff1a;global average pooling 网络的整体结构&#xff1a; 网络结构 …

GDUT_专题三:B - Learning Languages

题目&#xff1a; The "BerCorp" company has got n employees. These employees can use m approved official languages for the formal correspondence. The languages are numbered with integers from 1 to m. For each employee we have the list of language…

MTCNN算法详解

The Multi-task Cascaded Convolutional Networks (MTCNN)算法出自深圳先进技术研究院&#xff0c;乔宇老师组&#xff0c;2016的ECCV。facenet中人脸对齐和特征提取就是用了这个网络。 算法流程图 MTCNN由3个网络结构组成&#xff08;P-Net,R-Net,O-Net&#xff09;。 &#…

GDUT_专题三:F - Built?

题目&#xff1a; There are towns on a plane. The -th town is located at the coordinates . There may be more than one town at the same coordinates.Ni(xi​,yi​) You can build a road between two towns at coordinates and for a cost of yen (the currency of J…

GDUT_专题四:L - Happy 2006 【欧拉函数】

题目&#xff1a; Two positive integers are said to be relatively prime to each other if the Great Common Divisor (GCD) is 1. For instance, 1, 3, 5, 7, 9...are all relatively prime to 2006. Now your job is easy: for the given integer m, find the K-th eleme…

E297: Write error in swap file

当我使用vim编辑一个常用的配置文件的时候出现一个错误&#xff1a;E297: Write error in swap file然后上网查找原因&#xff0c;说是磁盘空间不足&#xff0c;于是我就查看一下机器磁盘空间使用情况&#xff1a;sht-sgmhadoopdn-02:postgres:/usr/local/pgsql/data:>df -T…

沙盒测试账号:不允许创建 iTunes 账户

1.出现情况 不允许创建 iTunes 账户.jpg在设置里登陆沙盒账号提示&#xff1a; 不允许创建 iTunes 账户 此 Apple ID 目前无法用于 iTunes Store, 请稍后重试 正确方式&#xff1a; 沙盒测试账号只能在测试应用点击储值时&#xff0c;弹窗中输入账号&#xff0c;不能在设置里的…