赞
踩
提示:这里可以添加本文要记录的大概内容:
题目描述:
有一名科学家想要从一台古董电脑中拷贝文件到自己的电脑中加以研究。但此电脑除了有一
个 3.5 寸软盘驱动器以外,没有任何手段可以将文件拷贝出来,而且只有一张软盘可以使
用。因此这一张软盘是唯一可以用来拷贝文件的载体。
科学家想要尽可能多地将计算机中的信息拷贝到软盘中,做到软盘中文件内容总大小最大。
已知该软盘容量为 1474560 字节。文件占用的软盘空间都是按块分配的,每个块大小为
512 个字节。一个块只能被一个文件使用。拷贝到软盘中的文件必须是完整的,且不能采
取任何压缩技术。
输入描述:
第 1 行为一个整数 N,表示计算机中的文件数量。1 <= N <= 1000。
接下来的第 2 行到第 N+1 行(共 N 行),每行为一个整数,表示每个文件的大小 Si,单
位为字节。0 <= i < N,0 <= Si
输出描述:
科学家最多能拷贝的文件总大小。
补充说明:
为了充分利用软盘空间,将每个文件在软盘上占用的块记录到本子上。即真正占用软盘空间
的只有文件内容本身。
示例 1
输入:
3
737270
737272
737288
输出:
1474542
说明:
3 个文件中,每个文件实际占用的大小分别为 737280 字节、737280 字节、737792
字节。只能选取前两个文件,总大小为 1474542 字节。虽然后两个文件总大小更大且未超过
1474560 字节,但因为实际占用的大小超过了 1474560 字节,所以不能选后两个文件。
示例 2
输入:
6
400000
200000
200000
200000
400000
400000
输出:
1400000
说明:
从 6 个文件中,选择 3 个大小为 400000 的文件和 1 个大小为 200000 的文件,得到
最大总大小为 1400000。
也可以选择 2 个大小为 400000 的文件和 3 个大小为 200000 的文件,得到的总大小
也是 1400000。
题解:
软盘总容量是1474560 字节,每个块是512 个字节,总块是Math.ceil(1474560/512) = 2880块
每个文件也可以算出它的块数,很明显的背包问题, 所以就是转换成一个固定容量的背包,放入物品的数据。直接采用动态规划的思想来做。
使用二维数组dp[i][j],每个物品占用快数为fileBlock[i],占用空间fileSpace[i];
其中i就是取前i个物品,j就是占用的块容量是j。那么dp[i][j]的意思就是在前i个物品中取物品放入块容量是j的软盘中占用的最大空间数据。
然后就是初始化:
对于dp[i][0],也就是在一个块容量为0的软盘中放入前i个文件,肯定一个都放不了,那么就是0
所以dp[i][0] = 0;
对于dp[0][j],也就是在块容量为j的的软盘总放入第一个文件,所以这里就要判断j>=fileBlock[0],才能放入,否则放不下,也是0;
那么递归的第i个物品能占用的最大空间,就有两种情况
1.一个是第i个物品不放,那么它此时就等于
dp[i][j] = dp[i-1][j]
2.第i个物品放,那么前i-1个物品占用空间应该是j-fileBlock[i]
此时dp[i][j] = dp[i-1][j-fileBlock[i]] + fileSpace[i];
实际代码计算时候,这个里面必须有一个判断,就是j必须大于等于fileBlock[i],否则会出现负值,不合乎逻辑。
以下就是代码实现:
由于要求前n个物品,在块为2880里面返回的最大空间,所以返回的应该是dp[n-1][2880]才对。
- import java.util.Scanner;
-
- public class SoftCopy {
- public static void main(String[] args) {
- Scanner sc = new Scanner(System.in);
- int fileNum = sc.nextInt();
-
- int[] fileSpace = new int[fileNum];
- int[] fileBlock = new int[fileNum];
-
- for (int i = 0; i < fileNum; i++) {
- fileSpace[i] = sc.nextInt();
- fileBlock[i] = (int) Math.ceil(fileSpace[i] / 512.0);
- }
- int maxBlock = (int) Math.ceil(1474560 / 512);
- System.out.println("maxBlaock is :" + maxBlock);
- System.out.println(getDp(fileSpace, fileBlock, maxBlock));
- }
-
- private static int getDp(int[] fileSpace, int[] fileBlock, int maxBlock) {
- int dp[][] = new int[fileSpace.length][maxBlock + 1];
- for (int i = 0; i < fileSpace.length; i++) {
- for (int j = 0; j < maxBlock + 1; j++) {
- if (j == 0) {
- dp[i][0] = 0;
- continue;
- }
- if (i == 0) {
- if (j >= fileBlock[0]) {
- dp[0][j] = fileSpace[0];
- } else {
- dp[0][j] = 0;
- }
- continue;
- }
- if (j < fileBlock[i - 1]) {
- dp[i][j] = 0;
- continue;
- }
- dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - fileBlock[i - 1]] + fileSpace[i - 1]);
- }
- }
-
- return dp[fileBlock.length - 1][maxBlock];
- }
- }
验证结果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。