题目链接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=655
![](https://img-blog.csdn.net/20170705102606592)
题目:附件
题意:经典的最大值最小化问题。一些书和一些抄写员,分配任务使总的工作时间最短,即所有抄写员的时间的最大值最小。
题解:小白上有详细解释。
此题要注意的是
- 要求最后多解情况,尽量使得前面的员工工作量尽可能小,所以最后分割从后往前分。
- 用long long存储
- 考虑最后分组剩余,即斜杠没有都用完,则尽可能在前面插入 。
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAX=500+10;
typedef long long LL;
LL a[MAX];
int vis[MAX];
int N,m,k;
bool judge(int x)
{
LL subsum=0;
int cou=1;
for(int i=m-1; i>=0; i--)
{
subsum+=a[i];
if(subsum>x)
{
subsum=0;
i++;
cou++;
}
if(cou>k)
return false;
}
return cou<=k;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
cin>>N;
while(N--)
{
cin>>m>>k;
LL right=0;
LL left=0;
for(int i=0; i<m; i++)
{
// scanf("%lld",&a[i]);
cin>>a[i];
right+=a[i];
left=max(left,a[i]);
}
while(left<right)
{
LL mid=(left+right)/2;
if(judge(mid))
right=mid;
else
left=mid+1;
}
LL x0=right;
// cout<<x0<<endl;
memset(vis,0,sizeof(vis));
LL subsum=0;
for(int i=m-1; i>=0; i--)
{
subsum+=a[i];
if(subsum>x0)
{
subsum=0;
vis[i]=1;
i++;
k--;
}
}
while(k-1>0)
{
for(int i=0; i<=m; i++)
if(!vis[i])
{
vis[i]=1;
k--;
break;
}
}
for(int i=0; i<m; i++)
{
if(i) printf(" ");
//printf("%lld",a[i]);
cout<<a[i];
if(vis[i]) printf(" /");
}
printf("\n");
}
return 0;
}