[算法竞赛入门经典] UVA 714 - Copying Books

来源:互联网 发布:网络层设备 编辑:程序博客网 时间:2024/06/05 03:30
紫书P244 例题 8-10。直接二分查找最小值,倒着分段贪心。

倒着贪心有个注意的地方,题目要求分K堆。但有时贪心的时候会使堆数< K,也就是要保证K堆每堆都不能为空。

贪心时用一个条件限制一下即可。


#include <stdio.h>  #include <string.h>  #include <math.h>  #include <stdlib.h>  #include <algorithm>  #include <iostream>  #include <set>  #include <map>  #include <queue>  #include <stack>#include <assert.h>typedef long long LL;using namespace std;int main()  {      //freopen("test0.in", "r", stdin);      //freopen("test0.out", "w", stdout);      int T, k, m, a[1000], flag[1000];    scanf("%d", &T);    while(T--)    {        scanf("%d %d", &m, &k);        LL left = 1, right = 0, mid;        for(int i = 1; i <= m; ++i)        {            scanf("%d", &a[i]);            left = max((LL)a[i], left);            right += a[i];        }        LL ans;        int cnt;        while(left < right)        {            mid = (left + right) / 2;            cnt = 1;            ans = 0;            for(int i = 1; i <= m; ++i)            {                ans += a[i];                if(ans > mid)                {                    ++cnt;                    ans = a[i];                }            }            if(cnt <= k)            {                right = mid;            }            else            {                left = mid + 1;            }        }        cnt = ans = 0;        for(int i = m; i >= 1; --i)        {            ans += a[i];            if(ans > left || (i <= k - cnt - 1))//题目要求当有多个解时            {                                   //前面划分的尽量小,即倒着贪心                   flag[cnt++] = i;                ans = a[i];            }        }        --cnt;        for(int i = 1; i <= m; i++)        {            printf(i != m ? "%d ":"%d\n", a[i]);            if(flag[cnt] == i)            {                printf("/ ");                --cnt;            }        }    }    return 0;  }

0 0
原创粉丝点击