UVA 714 Copying Books

 

题意:按顺序给你N个数,将这N个数分成连续的M段,使得这M段每段的和中的最大值最小,输出最小值(1<=N<=100000,1<=M<=N,每个数在1到10000之间),如果有多种可能的话,尽量在前面进行划分。

思路:

1、由于函数具有单调性的特征,因此可以用二分枚举的办法去实现它,这与POJ3258有非常相似的地方,但这里不需要排序。

2、输出的时候需要用到贪心的思想,既尽量往前划分。

3、大概的思路就是二分枚举求得满足题意的最大值之后,然后以这个最大值通过从后往前的方式划分成段,如果剩余可划分段与i+1的值相等(尽量靠前),则将剩余的段往前划分,具体实现可以用一个标记数组use表示是否划分。

5、注意high_bound可能超int,所以需要long long 来存。

CODE:

 

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
using  namespace std;

const  int MAXN =  510;

int a[MAXN], use[MAXN];
long  long  low_bound, high_bound;
int n, m;

void init()
{
    low_bound = - 1;
    high_bound =  0;
    memset(use,  0sizeof(use));
}

int solve( int mid)
{
     int sum =  0, group =  1;
     for( int i = n- 1; i >=  0; i--)
    {
         if(sum + a[i] > mid)
        {
            sum = a[i];
            group++;
             if(group > m)  return  0;
        }
         else sum += a[i];
    }
     return  1;
}

void print( int high_bound)
{
     int group =  1, sum =  0;
     for( int i = n- 1; i >=  0; i--)
    {
         if(sum + a[i] > high_bound)
        {
            use[i] =  1;
            sum = a[i];
            group++;
        }
         else sum += a[i];
         if(m-group == i+ 1)
        {
             for( int j =  0; j <= i; j++)
                use[j] =  1;
             break;
        }
    }
     for( int i =  0; i < n- 1; i++)
    {
        printf( " %d  ", a[i]);
         if(use[i]) printf( " ");
    }
    printf( " %d\n ", a[n- 1]);
}

int main()
{
     int T;
    scanf( " %d%*c ", &T);
     while(T--)
    {
        init();
        scanf( " %d%d ", &n, &m);
         for( int i =  0; i < n; i++)
        {
            scanf( " %d ", &a[i]);
             if(low_bound < a[i]) low_bound = a[i];
            high_bound += a[i];
        }
         long  long x = low_bound, y = high_bound;
         while(x <= y)
        {
             long  long  mid = x+(y-x)/ 2;
             if(solve(mid)) y = mid- 1;
             else x = mid+ 1;
        }
        print(x);
    }
     return  0;
}

 

你可能感兴趣的:(copy)