uva 714 - Copying Books(贪心 最大值最小化 二分)

题目描述开头一大堆屁话,我还仔细看了半天。。其实就最后2句管用。意思就是给出n本书然后要分成k份,每份总页数的最大值要最小。问你分配方案,如果最小值相同情况下有多种分配方案,输出前面份数小的,就像字典序输出从小到大一样的意思。

这里用到贪心的方法,定义f(x)为真的条件是满足x为最大值使n本书分成k份,那么就是求x的最小值。如何确定这个x就是用的二分法,x一定大于0小于所有值的合,不断的二分再判断是否成立,成立就取左半边,不成立说明太小了就取右半边,写的时候还是没有把二分法理解透彻,我还怕会丢失那个值还特意去保存,事实上二分法最后结束得出来的x或y(二个数是相等的)就是每份的最大值。而如何确定这个最大值是否成立就是用贪心的方法,尽量的往右边拓展直到大于最大值的前一个为止。如果份数还没分完就到最后一个了,那就肯定是成立的。反之,如果份数分完了还没到最后一个那就是不成立。

输出的时候还得注意,得从后往前,因为前面的份数得要小,就得从后往前贪心,还有当剩余的跟份数一样的时候就不能贪心了,就要每一个都要分开了。这个就自己模拟数据看吧,加一减一的都得跟前面写的有关系。

还有两点要特别注意, 求和的时候会超int范围,因为一个最大可达1×10^8,而最多有500个,超过了4×10^9了。所以要用long long。还有一点是输出的时候最后一个数字后面不能多打一个空格不然会报PE的。

AC代码:

#include<cstdio>
#include<ctype.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<ctime>
using namespace std;
#define NMAX 505
#define ll long long
int a[NMAX];
int ans[NMAX];
int solve(ll Max,int n,int k)
{
    int i=0,j=0,nct=0;
    ll sum=0;
    while(nct < k)
    {
        sum+=a[j];
        if(sum > Max && i == j) return 0;
        if(sum > Max)
        {
            nct++;
            i = j;
            sum = 0;
        }
        else j++;
        if(j == n) return 1;
    }
    return 0;
}

void path(ll Max,int n,int k)
{
    int nct = 0,i=n-1;
    ll sum=0;
    while(i>0)
    {
        sum+=a[i];
        if(sum > Max)
        {
            sum = 0;
            ans[i] = 1;
            nct++;
        }
        else i--;
        if(i == k-nct-2)
        {
            for(int j = 0; j <= i; j++)
                ans[j] = 1;
            break;
        }
    }
    for(int i = 0; i < n; i++)
    {
        if(i == n-1) printf("%d",a[i]);
        else printf("%d ",a[i]);
        if(ans[i]) printf("/ ");
    }
    printf("\n");
}

int main()
{
    int i,n,k,m;
    scanf("%d",&n);
    while(n--)
    {
        memset(ans,0,sizeof(ans));
        scanf("%d%d",&m,&k);
        ll sum = 0;
        for(i = 0; i < m; i++)
        {
            scanf("%d",&a[i]);
            sum += a[i];
        }
        ll x=0,y=sum,z;
        while(x<y)
        {
            z = x+(y-x)/2;
            if(solve(z,m,k))
                y = z;
            else x = z+1;
        }
        path(x,m,k);
    }
    return 0;
}

uva 714 - Copying Books(贪心 最大值最小化 二分),布布扣,bubuko.com

时间: 2024-12-26 03:19:33

uva 714 - Copying Books(贪心 最大值最小化 二分)的相关文章

UVa 714 Copying books 贪心+二分 最大值最小化

题目大意: 要抄N本书,编号为1,2,3...N, 每本书有1<=x<=10000000页, 把这些书分配给K个抄写员,要求分配给某个抄写员的那些书的编号必须是连续的.每个抄写员的速度是相同的,求所有书抄完所用的最少时间的分配方案. 题目中的要求是去求划分的子序列的最大值尽量小,最大值最小化,如果从划分的角度看,无法获得好的思路,我们可以从值得角度考虑,所要求的最小的最大值必定是从[amax,sum(总和)]中取得的,那么我们可以二分法的方式猜测一个数字,看它是否满足要求,如果满足要求,我们可

UVa 714 Copying Books(贪心 二分)

题意  把m数分成k组  使每组数的和的最大值最小  如果有多种分法 靠前的组的和尽量小 关键是找出那个最小的最大值   可以通过二分来找出  开始左端点为m个数中最大的数  右端点为m个数的和  若中点能将m个数分为小于等于k组  比它大的肯定都是可以的  中点变为右端点   否则中点变成左端点 然后就可以贪心逆向模拟了  从后往前每组选择尽量多的数直到剩下的数等于组数 #include <bits/stdc++.h> using namespace std; typedef long lo

uva 714 Copying Books (二分)

uva 714 Copying Books Before the invention of book-printing, it was very hard to make a copy of a book. All the contents had to be re-written by hand by so called scribers. The scriber had been given a book and after several months he finished its co

UVa 714 - Copying Books 二分答案

题目链接:714 - Copying Books 解题思路 具体处理方法见代码 /************************************************************** Problem: User: youmi Language: C++ Result: Accepted Time: Memory: ****************************************************************/ //#pragma comm

UVA 714 Copying Books 抄书 (二分)

题意:把一个包含m个正整数的序列划分成k个非空的连续子序列.使得所有连续子序列的序列和Si的最大值尽量小. 二分,每次判断一下当前的值是否满足条件,然后修改区间.注意初始区间的范围,L应该为所有正整数中的最大值,否则应该判断时注意.输出解的时候要使字典序最小,所以从后面贪心. #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxm = 501; ll p[maxm]; bool vis[

【NOIP提高组2015D2T1】uva 714 copying books【二分答案】——yhx

Before the invention of book-printing, it was very hard to make a copy of a book. All the contents hadto be re-written by hand by so called scribers. The scriber had been given a book and after severalmonths he finished its copy. One of the most famo

UVA 714 Copying Books

题意: 要抄N本书,编号为1,2,3...N, 每本书有1<=x<=10000000页, 把这些书分配给K个抄写员,要求分配给某个抄写员的那些书的编号必须是连续的.每个抄写员的速度是相同的,求所有书抄完所用的最少时间的分配方案. 分析: 这个题以前做过.就是先二分出来,最大的区间最小值.然后一重循环查找输出/就好 代码: #include <iostream>#include <cstring>#include <cstdio>#include <al

uva714 - Copying Books(最大值最小化)

题目:uva714 - Copying Books(最大值最小化) 题目大意:给出n本书,每本书的值代表这本书的页数.然后给定m个scribers,每个scriber至少要抄一本书,或者连续的几本书.每个scriber的工作量就等于他要抄的书的页数之和.问怎样划分能使的scribers中工作量的最大值最小.这里要求答案如果有多种的话就输出前面的和比较小的那个划分. 解题思路:最大值最小化问题. 二分尝试可能的最大值,然后如果在这个最大值的情况下可以划分的话,说明最大值可能是这个值,也可能更小.如

UVA714- Copying Books(最大值最小化)

题意:k份书稿分成m份,使得每份的和最小 思路:典型最大值最小化问题,使用贪心+二分.贪心的是每次尽量将元素往右边划分,二分查找最小的x满足m个连续的子序列和S(i)都不超过x. 因为输出的原因,在划分时就从后往前尽量划分. #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long l