uva714-复制书稿

题目链接 http://acm.hust.edu.cn/vjudge/problem/19689

 

解题思路

寻找最小上界用二分法

打印方案时从右边(尾)尽量往左边(头)划分。段数不够的话,从最左边往右一个一个划分。

 

代码

#include<stdio.h>
#include<string.h>
//#define LOCAL
typedef long long ll;
int div, n;
ll book[505];
bool flag[505];
void Search(ll l, ll r)
{
    while(l<r) {
        bool flag1 = false;
        ll mid = (l+r)/2;
        ll sum = 0, divide = 1;
        for(int i=0; i<n; i++) {
            if(sum<mid && sum+book[i]<mid) sum+=book[i];
            else if(book[i]<mid){ divide++; sum=0; sum+=book[i]; }
                else { flag1 = true; break; }
        }
        if(flag1 || divide > div) l = mid+1;
        else r = mid;
    }
//    printf("%d\n", l);
    ll sum = 0;
    for(int i=n-1; i>=0; i--) {
        if(sum<l && sum+book[i]<l) sum+=book[i];
        else { 
            sum = 0; flag[i] = true;
            sum+=book[i];
        }
    }
    int di=1; int pos=0; for(int i=n-1; i>=0; i--) if(flag[i]) di++;
    if(di != div) 
         for(int i=0; i<n&&di!=div; i++) if(!flag[i]) { flag[i] = true; di++; }
    for(int i=0; i<n; i++) if(flag[i] && i!=n-1) printf("%lld / ", book[i]);
        else if(i!=n-1)printf("%lld ", book[i]); else printf("%lld", book[i]);
}
int main()
{
    #ifdef LOCAL
        freopen("data.txt", "r", stdin);
        freopen("ans.txt", "w", stdout);
    #endif
    int cases; ll sum = 0;
    scanf("%d", &cases);
    while(cases--) {
        memset(flag, 0, sizeof(flag));
        scanf("%d%d", &n, &div);
        for(int i=0; i<n; i++) { scanf("%lld", &book[i]); sum+=book[i]; }
        Search(0, sum);
        printf("\n");
    }
    return 0;
}

 

posted @ 2016-08-17 09:16  啊嘞  阅读(294)  评论(0编辑  收藏  举报