714 - Copying Books
来源:互联网 发布:人工智能 招聘 深圳 编辑:程序博客网 时间:2024/06/09 14:05
Before theinvention of book-printing, it was very hard to make a copy of a book. All thecontents had to be re-written by hand by so called scribers. Thescriber 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 wasXaverius Endricus Remius Ontius Xendrianus (Xerox). Anyway, the work wasvery annoying and boring. And the only way to speed it up was to hire morescribers.
Once upon a time, there was a theater ensemble that wanted to play famousAntique Tragedies. The scripts of these plays were divided into many books andactors needed more copies of them, of course. So they hired many scribers tomake copies of these books. Imagine you have m books(numbered ) that may havedifferent number of pages ( ) and youwant to make one copy of each of them. Your task is to divide these booksamong k scribes, . Each book can beassigned to a single scriber only, and every scriber must get a continuoussequence of books. That means, there exists an increasing succession of numbers suchthat i-th scriber gets a sequence of books with numbersbetween bi-1+1 and bi.The time needed to make a copy of all the books is determined by the scriberwho was assigned the most work. Therefore, our goal is to minimize the maximumnumber of pages assigned to a single scriber. Your task is to find the optimalassignment.
Input
The input consistsof N cases. The first line of the input contains only positiveinteger N. Then follow the cases. Each case consists of exactly twolines. At the first line, there are two integers m and k, . At thesecond line, there are integers separatedby 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 dividedinto exactly k parts such that the maximum sum of a singlepart should be as small as possible. Use the slash character (`/') to separatethe parts. There must be exactly one space character between any two successivenumbers and between the number and the slash.
If there is more than one solution, print the one that minimizes the workassigned to the first scriber, then to the second scriber etc. But each scribermust be assigned at least one book.
Sample Input
2
9 3
100 200 300 400500 600 700 800 900
5 4
100 100 100 100100
Sample Output
100 200 300 400500 / 600 700 / 800 900
100 / 100 / 100 / 100100
题意:
按顺序给你N个数,将这N个数分成连续的M段,使得这M段每段的和中的最大值最小,输出最小值。如果有多种可能的话,尽量在前面进行划分。
思路:最小化最大值的问题
题目的最小的最大值一定大于等于单个元素的最大值(maxp),小于等于所有元素的和(tot)。在[maxp, tot]内寻找到分组不多于K组的最小数字(不多于K组:解释具体见下面的第二组数据分析)。为了与输出相统一,从后面开始统计分组,从而使得后面的区间和尽量大。使用二分搜索区间[maxp, tot]的数字,具体细节见代码。求出ans后,用贪心的思想输出序列,主要是控制‘/’的输出。具体细节见代码。
代码:
#include<cstdio>
#include<cstring>
//#include<iostream>
#include<algorithm>
using namespacestd;
const int maxm =500 + 5;
int m, k, p[maxm];
int last[maxm];
/*
每一组都要清空该数组为0;last[i]=1表示p[i]是分组区间的最后一个数,即输出p[i]后要输出斜杠
*/
int solve(longlong maxp) //从后向前统计组数
{
long long done = 0;
int ans = 1;//至少一组
for(int i = m-1; i >=0; i--)
{
if(done + p[i] <= maxp)
{
done += p[i];
}
else
{
ans++;
done = p[i];
}
}
return ans;
}
void print(longlong ans)
{
long long done = 0;
memset(last, 0, sizeof(last));
int remain = k-1;//剩余的斜杠数目
for(int i = m-1; i >= 0; i--)
{
if(done + p[i] > ans)
{
last[i] = 1;
remain--;
done = p[i];
}
else
{
done += p[i];
}
if(remain==i+1)
/*
当理论分组数目<K时,当剩余斜杠数目==剩余的数字个数,则每个数字后面都要输出斜杠,强制分组
*/
{
for(int j=0;j<=i;j++)
{
last[j]=1;
}
}
}
for(int i = 0; i < m-1; i++)
{
printf("%d ", p[i]);
if(last[i])
{
printf("/ ");
}
}
printf("%d\n", p[m-1]);
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%d%d", &m,&k);
long long tot = 0;
int maxp = -1;
for(int i = 0; i < m; i++)
{
scanf("%d", &p[i]);
tot += p[i];
maxp = max(maxp, p[i]);
}
long long L = maxp, R = tot;//使用 long long 否则有可能爆掉
while(L < R)
{
long long M = L + (R-L)/2;
//cout<<"当前的中点值是:"<<M<<endl;
//cout<<"分组的数目是:"<<solve(M)<<endl;
if(solve(M) < k)
//分组数目少,说明最大值太大,减小上限,不用保留上限
{
R=M-1;
}
else if(solve(M) == k)
//分组数目正好,但是不能说明最大值是最小的,减小上限,同时保留上限
{
R = M;
}
else //分组数目多,说明最大值太小,增大下限,不用保留下限
{
L = M+1;
}
}
print(L);
}
return 0;
}
“在[maxp, tot]内寻找到分组不多于K组的最小数字”分析如下:
以第二组数据为例,运行注释掉的代码:
示例输入:
1
5 4
100 100 100 100100
对应输出:
当前的中点值是:300
分组的数目是:2
当前的中点值是:199
分组的数目是:5
当前的中点值是:249
分组的数目是:3
当前的中点值是:224
分组的数目是:3
当前的中点值是:211
分组的数目是:3
当前的中点值是:205
分组的数目是:3
当前的中点值是:202
分组的数目是:3
当前的中点值是:200
分组的数目是:3
100 / 100 / 100 /100 100
分析:此组数据始终没有找到适合的M值使得solve(M) == k,当L==R时,退出了二分搜索循环,此时分组数目为3.
如果输出的时候不强制分组,输出应该是:
100 / 100 100 /100 100
但是根据题目要求,必须要输出K-1个斜杠,所以必须要考虑强制分组。
- uva 714 Copying Books
- UVa 714 - Copying Books
- uva 714 - Copying Books
- uva 714 - Copying Books
- 714 - Copying Books
- UVA 714 Copying Books
- UVa:714 Copying Books .
- uva 714 Copying Books
- Uva 714 - Copying Books
- uva 714 Copying Books
- 714 - Copying Books
- UVa 714 Copying Books
- Uva - 714 - Copying Books
- UVA 714 - Copying Books
- UVa 714 Copying Books
- uva 714 - Copying Books
- UVA - 714 Copying Books
- uva 714 Copying Books
- Android Studio功能
- Android开发之性能调优工具
- leetcode:Valid Palindrome 菜鸟解法
- 120 - Stacks of Flapjacks
- hibernate:java.math.BigInteger cannot be cast to java.lang.Long
- 714 - Copying Books
- 1152 - 4 Values whose Sum is 0
- 1442 - Cav
- 1451 - Average
- 网站加速--服务器编写篇(转)
- 计算器的实现——基础篇(一)
- jetty嵌入式 webApp开发(Simple Demo)
- 1471 - Defense Lines
- 1605 - Building for UN