抄书问题之二

来源:互联网 发布:php修改时区 编辑:程序博客网 时间:2024/04/29 17:50

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     */    // 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][n];    }    //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][n];    }    };




0 0
原创粉丝点击