题目背景
大多数人的错误原因:尽可能让前面的人少抄写,如果前几个人可以不写则不写,对应的人输出0 0。
不过,已经修改数据,保证每个人都有活可干。
题目描述
现在要把m本有顺序的书分给k给人复制(抄写),每一个人的抄写速度都一样,一本书不允许给两个(或以上)的人抄写,分给每一个人的书,必须是连续的,比如不能把第一、第三、第四本书给同一个人抄写。
现在请你设计一种方案,使得复制时间最短。复制时间为抄写页数最多的人用去的时间。
输入输出格式
输入格式:
第一行两个整数m,k;(k≤m≤500)
第二行m个整数,第i个整数表示第i本书的页数。
输出格式:
共k行,每行两个整数,第i行表示第i个人抄写的书的起始编号和终止编号。k行的起始编号应该从小到大排列,如果有多解,则尽可能让前面的人少抄写。
输入输出样例
输出样例#1:
1 5 6 7 8 9
分析:
本题题意是求“复制时间最短。复制时间为抄写页数最多的人用去的时间”,像这种最大值最小化问题一般都是二分答案,那么OK函数则不难想到运用贪心求解。
CODE:
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 const int M=505; 5 int n,k; 6 int page[M]; 7 int st[M],en[M]; 8 bool ok(int s){ 9 int now=0,o=0; 10 for (int i=1;i<=n;i++){ 11 if (o+page[i]>s) now++,o=0; 12 o+=page[i]; 13 if (page[i]>s) return false; 14 //if (s==15) cout<<i<<" "<<now<<endl; 15 } 16 if (now>=k) return false; 17 return true; 18 } 19 int main(){ 20 cin>>n>>k; 21 int r=0; 22 for (int i=1;i<=n;i++) 23 cin>>page[i],r+=page[i]; 24 int l=0; 25 while (l<=r){ 26 int mid=(l+r)/2; 27 if (ok(mid)) r=mid-1; 28 else l=mid+1; 29 } 30 int o=0,now=k; 31 en[k]=n; 32 //cout<<l<<endl; 33 for (int i=n;i>=1;i--){ 34 if (o+page[i]>l) st[now--]=i+1,en[now]=i,o=0; 35 o+=page[i]; 36 } 37 st[1]=1; 38 for (int i=1;i<=k;i++){ 39 cout<<st[i]<<" "<<en[i]<<endl; 40 } 41 //system("pause"); 42 return 0; 43 }