您的位置:首页 > 运维架构

UVa 714 Copying Books 二分 + 贪心 (最大值最小化问题)

2013-06-26 20:17 417 查看
/**
*  最大值最小化问题: 二分法。  刘汝佳那本白书上也说的很详细。
*     先把最大值的可能区间计算出来,也就是[0, maxAns] maxAns 就是所有页数总和。
*  然后再在答案区间里先把“最大值最小化”。
*     得到最小化后的最大值以后,就可以根据这个最大值来对最终答案进行计算。
*  如何分区,也就是计算最后答案ans:  这里就要用到贪心思想,因为题目要求
*  如果有多种可能情况,让区间集合所含的元素数从小到大排列。这样就可以贪心地
*  从所有pages的最后一个元素往前遍历来进行划分区间,只要其总和不大于之前所求的最大值,
*  就归到那个区间。
*     在把所有区间分好后,还有个情况就是,这个时候可能需要3个斜杠来分4个区间,
*  然而只用了2个(比如样例2),这样还有一个斜杠没用到,就再用贪心,把pages从第一个开始往后扫,
*  如果当前pages不用划斜杠,而剩余斜杠数大于0,则在这里添个斜杠。
*/

#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <algorithm>
#define INF 0x7fffffff
#define MAXS 501
#define LL long long
using namespace std;
int m, k;
LL maxAns;
int pages[MAXS], ans[MAXS];

bool judge(LL x) {
    int sum = 0, t = k;
    for(int i = 0; i < m; i ++) {
        sum += pages[i];
        if(sum > x) {
            i --;
            sum = 0;
            t --;
        }
        if(!t) {
            if(i != m - 1) return false;
            else return true;
        }
    }
    return true;
}

void solve() {
    memset(ans, 0, sizeof(ans));
    LL l, r, cur;
    l = 0; r = maxAns;
    while(l < r) {
        cur = (l + r) / 2;
        if(judge(cur))   r = cur;
        else             l = cur + 1;
    }
    int sum = 0;
    for(int i = m - 1; i >= 0; i --) {
        sum += pages[i];
        if(sum > r) {
            sum = 0;
            ans[++ i] = 1;
            k --;
        }
    }
    int i = 1;
    while(k > 1) {
        for(; i < m; i ++ ) {
            if(!ans[i]) {
                ans[i] = 1;
                k --;
                break;
            }
        }
    }
    printf("%d", pages[0]);
    for(int i = 1; i < m; i ++) {
        if(ans[i]) printf(" /");
        printf(" %d", pages[i]);
    }
    printf("\n");
}

int main()
{
    int t;
    scanf("%d", &t);
    while(t --) {
        maxAns = 0;
        scanf("%d%d", &m, &k);
        for(int i = 0; i < m; i ++) {
            scanf("%d", &pages[i]);
            maxAns += pages[i];
        }
        solve();
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: