Copying Books(最大化最小值问题)

本文介绍了一种将图书抄写任务高效分配给多个抄写员的方法,目标是最小化完成所有书籍抄写的总时间,同时确保每位抄写员负责连续编号的书籍。

点击打开链接

Problem Description
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 copy. One of the most famous scribers lived in the 15th century and his name was Xaverius Endricus Remius Ontius Xendrianus (Xerox). Anyway, the work was very annoying and boring. And the only way to speed it up was to hire more scribers.

Once upon a time, there was a theater ensemble that wanted to play famous Antique Tragedies. The scripts of these plays were divided into many books and actors needed more copies of them, of course. So they hired many scribers to make copies of these books. Imagine you have m books (numbered 1, 2 ... m) that may have different number of pages (p1, p2 ... pm) and you want to make one copy of each of them. Your task is to divide these books among k scribes, k <= m. Each book can be assigned to a single scriber only, and every scriber must get a continuous sequence of books. That means, there exists an increasing succession of numbers 0 = b0 < b1 < b2, ... < b k-1 <= bk = m such that i-th scriber gets a sequence of books with numbers between bi-1+1 and bi. The time needed to make a copy of all the books is determined by the scriber who was assigned the most work. Therefore, our goal is to minimize the maximum number of pages assigned to a single scriber. Your task is to find the optimal assignment.
 

Input
The input consists of N cases. The first line of the input contains only positive integer N. Then follow the cases. Each case consists of exactly two lines. At the first line, there are two integers m and k, 1 <= k <= m <= 500. At the second line, there are integers p1, p2, ... pm separated by spaces. All these values are positive and less than 10000000.
 

Output
For each case, print exactly one line. The line must contain the input succession p1, p2, ... pm divided into exactly k parts such that the maximum sum of a single part should be as small as possible. Use the slash character ('/') to separate the parts. There must be exactly one space character between any two successive numbers and between the number and the slash. < br>< br>If there is more than one solution, print the one that minimizes the work assigned to the first scriber, then to the second scriber etc. But each scriber must be assigned at least one book.
 

Sample Input
  
2 9 3 100 200 300 400 500 600 700 800 900 5 4 100 100 100 100 100
 

Sample Output
  
100 200 300 400 500 / 600 700 / 800 900 100 / 100 / 100 / 100 100


这个题和 Monthly Expense  基本差不多的,但是在输出的时候,要把具体的怎么分组输出来,但是在输出的时候,并不是很容易分组就输出了。

题意:

要抄N本书,编号为1,2,3...N, 每本书有1<=x<=10000000页, 把这些书分配给K个抄写员,要求分配给某个抄写员的那些书的编号必须是连续的。每个抄写员的速度是相同的,求所有书抄完所用的最少时间的分配方案。



#if 1
#include<cstdio>
#include<cstring>

int  T,n,c,a[510],b[510],ans[510],left,right,mid;
int check(int max)
{
    int j,num=0,tot=0;
    memset(b,0,sizeof(b));
    for(j=n;j>=1;j--)
    {
        if(tot+a[j]<=max&&j>=c-num)
            tot+=a[j];
        else
        {
            ++num;
            tot=a[j];
            b[j]=1;
        }
    }
    if(num+1==c)
    {
        for(j=1;j<=n;j++)
            ans[j]=b[j];
        return 1;
    }
    else return 0;
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        left=0;
        right=0;
        scanf("%d%d",&n,&c);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            right+=a[i];
            if(a[i]>left) 
				left=a[i];
        }
        memset(ans,0,sizeof(ans));
        
        while(left<=right)
        {                        
            mid=(left+right)/2;
            
            if(check(mid)==1)
                right=mid-1;
            else 
				left=mid+1;
        }
        for(int i=1;i<n;i++)
        {
            if(ans[i]==1)
                printf("%d / ",a[i]);
            else 
				printf("%d ",a[i]);
        }
        printf("%d\n",a[n]);
    }
    return 0;
}

#endif














### 如何使用G1垃圾回收器解决CMS导致的内存碎片化问题 #### G1垃圾回收器简介 G1(Garbage First)是一种并行与并发相结合的垃圾回收器,旨在提供高吞吐量的同时降低停顿时间。它通过将堆划分为多个大小相等的区域(Region),并对这些区域进行优先级排序来实现高效的垃圾回收过程[^2]。 #### 内存碎片化的成因 传统的CMS(Concurrent Mark-Sweep)垃圾回收器虽然能够快速清理不可达对象,但由于其不执行压缩操作,容易导致内存碎片化。这种现象会使得即使有足够的总内存空间可用,也无法满足连续的大对象分配请求[^4]。 #### G1如何缓解内存碎片化 G1通过以下机制有效解决了由CMS引发的内存碎片化问题: 1. **分代设计** 和其他现代JVM垃圾回收器一样,G1也采用了分代假设的设计理念,即新生代和老年代的概念被保留下来。然而,在实际分区时,整个Java堆会被细分成若干个固定大小的小块——称为Regions。每一块都可以独立属于某个特定世代或者跨世代共享。 2. **混合收集模式** 在每次Full GC之前,G1会选择那些含有最多可回收空间的regions作为候选集先行处理,这就是所谓的“garbage-first”的含义所在。这种方式不仅提高了效率,还减少了全局扫描带来的性能开销[^1]。 3. **复制算法的应用** 对于年轻代中的存活对象,G1采用的是经典的复制算法(Copying Algorithm)。这意味着每当有新的对象进入Eden区满载之后触发Minor GC时,所有仍然活着的对象都会被移动到Survivor区或其他地方去。由于涉及到物理地址的变化,自然也就消除了任何可能存在的内部碎片[^3]。 4. **并发标记阶段优化** 为了进一步缩短STW(Stop-The-World)暂停周期长度,G1引入了一个较长但不影响应用程序正常运行路径上的并发标记期。在此期间完成大部分必要的准备工作,比如确定哪些region应该参与下一轮清扫行动等等[^2]。 5. **动态调整heap size** 可以尝试对垃圾收集和堆扩展进行计时,以便它们在可预测和方便的时间发生。这虽然是一个更具挑战性的方法,但如果将其纳入全面考虑范围内的总体存储管理计划,则仍有助于减轻垃圾搜集造成的负担影响[^3]。 综上所述,相较于传统CMS仅依赖清除策略而无法应对长期积累下来的零散空闲片段情况而言,G1凭借自身独特的架构特点以及灵活多变的工作流程成功克服了这一难题。 ```java // 示例代码展示启用G1GC的方式之一 public class EnableG1Example { public static void main(String[] args){ System.out.println("This application uses G1 Garbage Collector."); } } ``` 编译选项设置如下所示: `javac -XX:+UseG1GC EnableG1Example.java` 运行命令则为: `java -XX:+UseG1GC EnableG1Example`
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值