OD统一考试(B卷)
分值: 200分
题解: Java / Python / C++
题目描述
有一名科学家想要从一台古董电脑中拷贝文件到自己的电脑中加以研究但此电脑除了有一个3.5寸软盘驱动器以外,没有任何手段可以将文件持贝出来,而且只有一张软盘可以使用,因此这一张软盘是唯一可以用来拷贝文件的载体。
科学家想要尽可能多地将计算机中的信息拷贝到软盘中,做到软盘中文件内容总大小最大。已知该软盘容量为1474560字节。文件占用的软盘空间都是按块分配的,每个块大小为512个字节。一个块只能被一个文件使用。拷贝到软盘中的文件必须是完整的,且不能采取任何压缩技术。
输入描述
第1行为一个整数N,表示计算机中的文件数量。1≤ N < 1000。
第2行到第N+1行(共N行),每行为一个整数,表示每个文件的大小 s i s_i si,单位为字节.0 < i < N,0< s i s_i si< 1000000
输出描述
科学家最多能拷贝的文件总大小。
备注
为了充分利用软盘空间,将每个文件在软盘上占用的块记录到本子上。即真正占用软盘空间的只有文件内容本身。
示例1
输入:
3
737270
737272
737288
输出:
1474542
题解
这个问题是经典的01背包 问题可以使用动态规划来解决。
软盘块容量相当于背包的容量,文件的大小相当于价值。
代码思路:
定义一个一维数组
dp
,其中dp[vol]
表示在软盘容量为vol
块的情况下,科学家最多能拷贝的文件总大小。初始时,将所有元素初始化为0。接下来,对于每个文件的大小,计算它所占的块数,即
block = ceil(size / 512)
,然后使用动态规划更新dp
数组。具体的更新方式是:
- 对于每个
vol
,如果vol >= block
,则更新dp[vol] = max(dp[vol], dp[vol - block] + size)
。这表示在软盘容量为vol
块的情况下,科学家可以选择拷贝当前文件,也可以选择不拷贝当前文件,取两者之间的最大值。最终,
dp[BLOCK_VOLUME]
即为科学家最多能拷贝的文件总大小。
Java
java
import java.util.Scanner;
/**
* @author code5bug
*/
public class Main {
public static void main(String[] args) {
// 软盘容量的块数
int BLOCK_VOLUME = 1474560 / 512;
Scanner scanner = new Scanner(System.in);
// 读取文件数量
int n = scanner.nextInt();
// 存储每个文件的大小
int[] sizes = new int[n];
for (int i = 0; i < n; i++) {
sizes[i] = scanner.nextInt();
}
int[] dp = new int[BLOCK_VOLUME + 1];
for (int size : sizes) {
int block = (int) Math.ceil((double) size / 512); // 存储文件所占的块数
for (int vol = BLOCK_VOLUME; vol >= block; vol--) {
dp[vol] = Math.max(dp[vol], dp[vol - block] + size);
}
}
System.out.println(dp[BLOCK_VOLUME]);
}
}
Python
python
# 软盘的块数
from math import ceil
# 软盘容量的块数
BLOCK_VOLUME = 1474560 // 512
n = int(input())
# 存储每个文件的大小
sizes = [int(input()) for _ in range(n)]
dp = [0] * (BLOCK_VOLUME + 1)
for size in sizes:
block = ceil(size / 512) # 存储文件所占的块数
for vol in range(BLOCK_VOLUME, block - 1, -1):
dp[vol] = max(dp[vol], dp[vol - block] + size)
print(dp[BLOCK_VOLUME])
C++
cpp
#include <iostream>
#include <vector>
using namespace std;
int main() {
// 软盘容量的块数
const int BLOCK_VOLUME = 1474560 / 512;
int n;
cin >> n;
// 存储每个文件的大小
vector<int> sizes(n);
for (int i = 0; i < n; ++i) {
cin >> sizes[i];
}
// dp数组初始化
vector<int> dp(BLOCK_VOLUME + 1, 0);
for (int size : sizes) {
// 存储文件所占的块数
int block = (size - 1) / 512 + 1;
for (int vol = BLOCK_VOLUME; vol >= block; --vol) {
dp[vol] = max(dp[vol], dp[vol - block] + size);
}
}
cout << dp[BLOCK_VOLUME] << endl;
return 0;
}
相关练习题
题号 | 题目 | 难易 |
---|---|---|
LeetCode 416 | 416. 分割等和子集 | 中等 |
LeetCode 474 | 474. 一和零 | 中等 |
LeetCode 494 | 494. 目标和 | 中等 |
🙏整理题解不易, 如果有帮助到您,请给点个赞 ❤️ 和收藏 ⭐,让更多的人看到。🙏🙏🙏