题目大意:
有m本书,k个抄写员。m本书的页码分别为 p1,p2……pm……。他们同时开始抄写且工作效率相同。要求分配给抄写员们若干书,每个抄写员要抄写的书的顺序必须是连续相邻的。
请你分配书使他们在最少的时间里完成抄写任务。
分析:
使每个抄写员分配到的页数的最大值尽可能小。最大值的最小化问题加二分法应用。
输入输出案例:
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
代码如下:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 6 int n,k; 7 int a[505]; 8 long long tot; 9 int maxa; 10 11 void Init() 12 { 13 cin>>n>>k; 14 tot=0; 15 maxa=-1; 16 for(int i=0;i<n;i++) 17 { 18 cin>>a[i]; 19 tot+=a[i]; 20 maxa=max(a[i],maxa); //明确最大页码的范围是:[maxa,tot]. 21 } 22 } 23 24 int deal(long long num) 25 { 26 long long c=0; 27 int sum=1; 28 for(int i=0;i<n;i++) 29 if(c+a[i]<=num) 30 c+=a[i]; 31 else 32 { 33 c=a[i]; 34 sum++; 35 } 36 return sum; 37 } 38 39 void print(long long num) 40 { 41 int last[510]; 42 long long done = 0; 43 memset(last, 0, sizeof(last)); 44 int remain = k; 45 for(int i = n-1; i >= 0; i--) 46 { 47 if(done + a[i] > num || i+1 < remain) 48 { 49 last[i] = 1; 50 remain--; 51 done = a[i]; 52 } 53 else 54 done += a[i]; 55 56 } 57 for(int i = 0; i < n-1; i++) 58 { 59 printf("%d ", a[i]); 60 if (last[i]) 61 printf("/ "); 62 } 63 printf("%d ", a[n-1]); 64 } 65 66 void Do() 67 { 68 long long l,r,m; 69 l=maxa; 70 r=tot; 71 while(l<r) 72 { 73 m=l+(r-l)/2; //二分,将抄写页码最大值区间缩小一半 74 if(deal(m)<=k) r=m; //如果当前分配方法能分配额份数小于抄写员人数,则应把区间上限减小(区间缩小一半), 75 else l=m+1; //如果当前分配使得分配份额大于抄写员人数,则把区间下限增大至m+1; 76 } 77 print(l); // l>=r,此分配方案可行,输出 78 } 79 80 int main() 81 { 82 int T,t; 83 cin>>T; 84 t=T; 85 while(T--) 86 { 87 Init(); 88 Do(); 89 } 90 return 0; 91 }*/