为每个学生分配最少的页数

时间:2016-04-19 13:41:36

标签: algorithm

任何人都可以提供正确的算法来解决这个问题。不是代码只是算法。谢谢。

  

你有N本书。每本ith书都有Pi页数。   您必须为M个学生分配书籍,以便最大限度地分配给学生的最大页数。一本书将分配给一名学生。每个学生必须至少分配一本书。

     

注意:如果无法进行有效的分配,则返回-1,并且分配应该是连续的顺序。

这是问题陈述的a link

3 个答案:

答案 0 :(得分:6)

将每个学生的最大值设置为X页。

要检查这是否可行,只需开始为第一个学生分配书籍,直到下一本书超过阈值X.然后切换到下一个等等(这是有效的,因为他们说分配需要是连续的)。

如果你的书用完了,那么这是可行的(你总是可以回去给学生更少的书来阅读以适应其他学生)。如果你的学生用完了,那就不行了。

此检查将为O(N),其中N是书籍数量。

现在你有了这个,做二进制搜索X. Complexity是O(NlogM),其中N是书籍数,M是总页数。

答案 1 :(得分:3)

好的,我将解释上述帖子中@Sorin的含义。

我们的基本方法设定了一个上限,然后检查我们是否可以根据这个上限为学生分配书籍,即。检查如果真的可以分配?

对于eg-Say我们有12,67,34,90作为我们的四本书,它们的值表示该书中的页数。假设我们的学生人数是2。 并且说我将上限设置为20(假设)。 现在让我们开始为学生分配书籍。

  1. 为学生1分配第一本12页的书(这是可行的,因为每个学生最多限制为20页)。
  2. 尝试再次向学生1分配67页的书籍,但这变得不可行,因为现在总数变为12 + 67 = 79,超过了上限,即20。
  3. 所以现在又向第二名学生分配67页书,再次超过限制再次变得不可行。
  4. 现在因为他们没有留下学生。因此,这意味着我们错误地估计了我们的上限。
  5. 所以现在我们再次增加上限让我们说113,然后所有的书都分配给学生。
  6. 好的,现在剩下的就是如何找到这个上限。

    答案 - 二进制搜索。

    说明 -

    1. 设置l = 0,r = Integer.MAX_VALUE,mid(上限)=(l + r)/ 2.
    2. 检查上述算法的上限。

      一个。如果基于算法接受此值。设r = mid-1(即检查它是否适用于较小的限制)。

      湾如果不接受此值,则设置l = mid + 1(即检查它是否在更高的限制下工作)。

    3. 3.直到l<河

      (注) - 最初检查(学生人数>图书)是否返回-1;

答案 2 :(得分:1)

这是二元搜索的经典例子答案。 所以你需要做一个观察: 如果增加学生人数(M),则要分配的最大页数(P_max)会减少。 当M = N时,将发生P_max(lo)的最小值。答案是所有P_i的最大值。 当M = 1时,将发生P_max(hi)的最大值。答案是所有P_i的总和。

现在,我们定义一个函数F(x),如果我们可以为每个学生分配最多x个页面并且仍然满足最多M个学生,则该函数将返回true。

如果我们可以从第一本书开始分配x页的连续总和,则可以通过遍历页数组(P)并将学生数增加1来计算F(x)。

让我们将F(x)称为allocateBooks函数。 参数为页数组(P),书数(n),最大页数(x)和学生数(m)。

bool allocateBooks(int64_t P[], int64_t n, int64_t x, int64_t m){
    int64_t sum = 0, count = 1;
    for(int64_t i = 0; i < n; i ++){
        sum += P[i];
        if(sum > x){
            count ++;
            sum = P[i];
        }
    }
    return (count <= m);
}

观察,对于特定情况:F(lo)=假,F(lo + 1)=假,...,F(lo + k)=假,F(lo + k + 1)=真,。 。,和F(hi)=真。

所以,我们可以看到它本质上是单调的。

在这种情况下,我们要找到第一个真值,(lo + k + 1)。二进制搜索救援。

int main() {
    int64_t n;
    cin >> n;
    int64_t P[n], sum = 0, maxval = 0;
    for(int64_t i = 0; i < n; i ++){
        cin >> P[i];
        sum += P[i];
        maxval = max(maxval, P[i]);
    }
    int64_t m;
    cin >> m;

    // find the minimum of max pages in books
    // Observation : when m = 1, ans = sum; while when m = n, ans = maxval
    // Thus when m increases ans decreases
    int64_t lo = maxval, hi = sum, mid;
    while(hi > lo) {
        mid = lo + (hi - lo) / 2;
        if(allocateBooks(P, n, mid, m)){
            hi = mid;
        } else {
            lo = mid + 1;
        }
    }
    cout << hi << "\n";
    return 0;
}