题目描述
有若干个文件,使用刻录光盘的方式进行备份,假设每张光盘的容量是500MB,求使用光盘最少得文件分布方式,所有文件的大小都是整数的MB,且不超过500MB,文件不能分割、分卷打包。
输入描述
一组文件大小的数据
输出描述
使用光盘的数量
用例1
输入:
10,50,30,200,400
输出:
3
用例2
输入:
1,100,200,300
输出:
2
Java
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读入文件大小数据
int[] fileSizes = Arrays.stream(scanner.nextLine().split(",")).mapToInt(Integer::parseInt).toArray();
// 对文件大小进行排序
Arrays.sort(fileSizes);
// 最少需要的光盘数量的范围
int min = 0;
int max = fileSizes.length + 1;
while (min < max) {
// 二分查找
int mid = (min + max) / 2;
// 初始化光盘大小数组
int[] discs = new int[mid];
Arrays.fill(discs, 500);
boolean flag = true;
// 从大到小遍历文件大小
for (int i = fileSizes.length - 1; i >= 0; i--) {
int fileSize = fileSizes[i];
// 对光盘大小数组进行排序
Arrays.sort(discs);
// 将文件存储到剩余空间最大的光盘中
if (discs[mid - 1] >= fileSize) {
discs[mid - 1] -= fileSize;
} else {
// 剩余空间最大的光盘都无法存储该文件,需要增加光盘数量
flag = false;
break;
}
}
if (flag) {
// 光盘数量可以更少,继续缩小范围
max = mid;
} else {
// 光盘数量需要增加,扩大范围
min = mid + 1;
}
}
// 输出最少需要的光盘数量
System.out.println(min);
}
}
JavaScript
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.on('line', (line) => {
// 读入文件大小数据
const fileSizes = line.split(',').map(Number).sort((a, b) => b - a);
// 最少需要的光盘数量的范围
let min = 0;
let max = fileSizes.length + 1;
while (min < max) {
// 二分查找
const mid = Math.floor((min + max) / 2);
// 初始化光盘大小数组
const discs = new Array(mid).fill(500);
let flag = true;
// 从大到小遍历文件大小
for (let i = 0; i < fileSizes.length; i++) {
const fileSize = fileSizes[i];
// 对光盘大小数组进行排序
discs.sort((a, b) => b - a);
// 将文件存储到剩余空间最大的光盘中
if (discs[0] >= fileSize) {
discs[0] -= fileSize;
} else {
// 剩余空间最大的光盘都无法存储该文件,需要增加光盘数量
flag = false;
break;
}
}
if (flag) {
// 光盘数量可以更少,继续缩小范围
max = mid;
} else {
// 光盘数量需要增加,扩大范围
min = mid + 1;
}
}
// 输出最少需要的光盘数量
console.log(min);
});
C++
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main() {
// 读入文件大小数据
string input;
getline(cin, input);
vector<int> fileSizes;
size_t pos = 0;
while ((pos = input.find(",")) != string::npos) {
int fileSize = stoi(input.substr(0, pos));
fileSizes.push_back(fileSize);
input.erase(0, pos + 1);
}
fileSizes.push_back(stoi(input));
// 对文件大小进行排序
sort(fileSizes.begin(), fileSizes.end());
// 最少需要的光盘数量的范围
int min = 0;
int max = fileSizes.size() + 1;
while (min < max) {
// 二分查找
int mid = (min + max) / 2;
// 初始化光盘大小数组
vector<int> discs(mid, 500);
bool flag = true;
// 从大到小遍历文件大小
for (int i = fileSizes.size() - 1; i >= 0; i--) {
int fileSize = fileSizes[i];
// 对光盘大小数组进行排序
sort(discs.begin(), discs.end());
// 将文件存储到剩余空间最大的光盘中
if (discs[mid - 1] >= fileSize) {
discs[mid - 1] -= fileSize;
} else {
// 剩余空间最大的光盘都无法存储该文件,需要增加光盘数量
flag = false;
break;
}
}
if (flag) {
// 光盘数量可以更少,继续缩小范围
max = mid;
} else {
// 光盘数量需要增加,扩大范围
min = mid + 1;
}
}
// 输出最少需要的光盘数量
cout << min << endl;
return 0;
}
Python
fileSizes = list(map(int, input().split(",")))
fileSizes.sort()
min = 0
max = len(fileSizes) + 1
while min < max:
mid = (min + max) // 2
discs = [500] * mid
flag = True
for i in range(len(fileSizes)-1, -1, -1):
fileSize = fileSizes[i]
discs.sort()
if discs[mid-1] >= fileSize:
discs[mid-1] -= fileSize
else:
flag = False
break
if flag:
max = mid
else:
min = mid + 1
print(min)