您的位置:首页 > 其它

抄书问题之二

2015-11-29 12:41 447 查看
Given n books( the page number of each book is the same) and an array of integer with size k means k people to copy
the book and the i th integer is the time i th person to copy one book). You must distribute the continuous id books to one people to copy. (You can give book A[1],A[2] to one people, but you cannot give book A[1], A[3] to one people, because book A[1] and
A[3] is not continuous.) Return the number of smallest minutes need to copy all the books.

样例

Given n = 
4
, array A
[3,2,4]
, .
Return 
4
( First person
spends 3 minutes to copy book 1, Second person spends 4 minutes to copy book 2 and 3, Third person spends 4 minutes to copy book 4. )

解题思路:

1.二分法,最优解。

2 动态规划,时间复杂度很高O(N2 × K)。

class Solution {
public:
/**
* @param n: an integer
* @param times: a vector of integers
* @return: an integer

b0f5
*/
// V1 二分法 (最优解)
int copyBooksII(int n, vector<int> ×) {
if(n == 0){
return 0;
}
int k = times.size();
if(k == 0){
return numeric_limits<int>::max();
}
else if (k == 1){
//只有一个抄书员
return times[0] * n;
}
//找出抄书时间的上下限
// 所有人以最快速度抄书,得到下限
// 所有人以最慢速度抄书,得到上限
int lowBound = numeric_limits<int>::max();
int highBound = numeric_limits<int>::min();
for(int i = 0; i < k; i++){
lowBound = min(lowBound, times[i]);
highBound = max(highBound, times[i]);
}
lowBound = lowBound * (( n + k - 1) / k);
highBound = highBound * (( n + k - 1) / k);

// 这里需要排序,将速度最快的排在前面,这样便于canCopy判断
sort(times.begin(), times.end());

// 二分法找出答案,每次二分时判断间值是否能在target时间内抄完
while(lowBound < highBound){
int mid = lowBound + (highBound - lowBound)/2;
if(canCopy(mid, n, times)){
highBound = mid;
}
else{
lowBound = mid + 1;
}
}
return lowBound;
}
// 判断是否能在target时间内抄写完成
// 优先选择最快的人抄写,因此事前需要对times 排序。
// 抄写速度最快的人尽量多抄
bool canCopy(int target, int n, vector<int> ×){
int totalBookCount = n;
int sum = 0;
int i = 0;
while(i < times.size()){
if(sum + times[i] <= target){
sum += times[i];
}
else if (i != (times.size() - 1) &&
times[++i] <= target){
sum = times[i];
}
else {
return false;
}

totalBookCount--;

if(totalBookCount <= 0){
return true;
}
}
return false;
}
//////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
// V2 : DP, time limit exceeded O(N2 * K)
int copyBooksII1(int n, vector<int> ×) {
// write your code here
if(n == 0){
return 0;
}
int k = times.size();
if(k == 0){
return numeric_limits<int>::max();
}
else if (k == 1){
//只有一个抄书员
return times[0] * n;
}
//f[i][j] 表示i个人抄j本书的最小耗时
vector<vector<int> > f(k+1, vector<int>(n+1, 0));
for(int j = 1; j <= n; j++){
f[0][j] = numeric_limits<int>::max();
f[1][j] = times[0] * j;
}
for(int i = 1; i <= k; i++){
for(int j = 1; j <= n; j++){
int minTime = numeric_limits<int>::max();
for(int x = 0; x <= j; x++){
minTime = min(minTime,
max(f[i-1][x], (j - x) * times[i-1]));
}
f[i][j] = minTime;
}
}
return f[k]
;
}
//V3 : DP 优化, 滚动数组空间优化,但是时间复杂度仍然比较高
int copyBooksII2(int n, vector<int> ×) {
// write your code here
if(n == 0){
return 0;
}
int k = times.size();
if(k == 0){
return numeric_limits<int>::max();
}
else if (k == 1){
//只有一个抄书员
return times[0] * n;
}
//f[i][j] 表示i个人抄j本书的最小耗时
vector<vector<int> > f(2, vector<int>(n+1, 0));
for(int j = 1; j <= n; j++){
f[0][j] = numeric_limits<int>::max();
}
for(int i = 1; i <= k; i++){
for(int j = 1; j <= n; j++){
int minTime = numeric_limits<int>::max();
for(int x = j; x >= 0; x--){
minTime = min(minTime,
max(f[(i-1)%2][x], (j - x) * times[i-1]));

if(f[(i-1)%2][x] < (j - x) * times[i-1]){
break;
}

}
f[i%2][j] = minTime;
}
}
return f[k%2]
;
}

};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  抄书问题之二