1. 程式人生 > >【二分與三分03】Copying Books

【二分與三分03】Copying Books

題目來源:

題目大意:

將n本頁數為p1,p2,……,pm(順序排列)的書分給k個抄寫員抄寫,每個抄寫員速度一樣且每個抄寫員只能抄寫編號相鄰的書,求抄寫時間最少的分組。

解題思路:

二分法與貪心。

通過二分法求出一個抄寫員最多需要抄寫的頁數,然後按照這個頁數來分組,前面的組儘量分得多一點。

初始下界和上界是最後一本書的頁數和所有書的總頁數。

分組標記的時候從後往前找,之後還要檢查分完了沒,沒分完就繼續直到分完。

試過從前面開始找但總是出錯放棄了x

AC程式碼:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define N 510
int n, k;
int c[N];

int check(long long mid)
{
    int i, j;
    long long num = 0;
    f = 0;
    for (i=0,j=0;i<n;i++)
    {
        num += c[i];
        if (num>mid)
        {
            j++;
            i--;
            num = 0;
        }
        if (j==k)
        {
            if (i!=n-1)
            {
                return 0;
            }
            else
            {
                return 1;
            }
        }
    }
    return 1;
}

long long apart(long long l, long long r)
{
    long long mid;
    while (l<r)
    {
        mid = (l+r)/2;
        if (check(mid))
        {
            r = mid;
        }
        else
        {
            l = mid + 1;
        }
    }
    return r;
}

void print(long long r)
{
    int flag[N] = {0};
    int i, x=k;
    long long sum = 0;
    for (i=n-1;i>=0;i--)
    {
        sum += c[i];
        if (sum>r)
        {
            i++;
            flag[i] = 1;
            x--;
            sum = 0;
        }
    }
    while (x>1)
    {
        for (i=1;i<n;i++)
        {
            if (!flag[i])
            {
                flag[i] = 1;
                x--;
                break;
            }
        }
    }
    for (i=0;i<n;i++)
    {
        if (flag[i])
        {
            printf("/ ");
        }
        printf("%d%c",c[i],i==n-1 ? '\n':' ');
    }
}

int main()
{
    int T, i;
    long long sum, min;
    scanf("%d",&T);
    while (T--)
    {
        scanf("%d%d",&n,&k);
        sum = 0;
        for (i=0;i<n;i++)
        {
            scanf("%d",&c[i]);
            sum += c[i];
        }
        min = c[i-1];
        print(apart(min,sum));
    }
    return 0;
}