这是一道关于求最大值最小化的问题。
虽然卡了不少时间,但是最后还是完全凭借自己的力量A的呢!yep~
题意:
现在有m本书,然后每本书有不同的页数,然后现在有k名员工,你可以把m本书划分给k名员工,也就是相当于把m划分成k个序列,你的任务是使所有的k个序列中的最大值尽量小。并输出划分情况。
当有多种划分情况时,必须保证第一个人所工作量最少,然后依次第二个。。。
思路:
最大值最小化的问题一般是用二分来做,因为可以就像猜数字一样去控制你所要到达的值!
这道题和书上有些不同。因为这里要保证从前往后工作的人工作量最少,所以我们必须要倒着for人,然后二分猜值,然后对于每个人尽量的往左边延展。
但是还有一个问题,因为这样划分出来的可能并没有分完全,所以我们还要从前往后对于没有获得划分的点进行划分,直到划分到k-1个斜杠为止。
接下来就是判断了,具体的看一下代码应该就能够懂的!
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<vector>
#include<algorithm>
using namespace std;
#define maxn 550
typedef long long ll;
ll a[maxn],dian[maxn],vis[maxn],cp[maxn];
ll m,k,tp=0; //m代表共有几本书,k代表分成几份;
bool is_ok(ll d){
memset(vis,0,sizeof(vis));
memset(dian,0,sizeof(dian));
bool ff=false;
int cnt=0;
ll sum=0;
ll duan=0,tx=-1;
for(int i=m;i>=1;i--){
if(a[i]>d){
duan++;
}
else if(sum+a[i]<=d){
sum+=a[i];
}
else if(sum+a[i]>d){
sum=a[i];
duan++;
dian[cnt++]=i+1;
vis[i+1]=1;
}
if(duan==k-1){
tx=i;
break;
}
}
if(duan<k-1){
for(int i=2;i<=m;i++){
if(duan==k-1){
ff=true;
break;
}
if(vis[i]) continue;
else if(!vis[i]){
if(a[i]<=d&&duan<k-1){
duan++;
vis[i]=1;
dian[cnt++]=i;
}
}
}
if(duan==k-1) ff=true; //一开始的时候,我忘记讨论这种情况,所以不能只在for里面判断,要不然会错,因为有可能是第一个的时候
if(ff){
tp=cnt;
for(int j=0;j<cnt;j++){
cp[j]=dian[j];
}
}
if(ff) return true;
else return false;
}
if(duan==k-1){
sum=0;
for(int i=tx;i>=1;i--){
sum+=a[i];
}
if(sum<=d){
tp=cnt;
for(int j=0;j<cnt;j++){
cp[j]=dian[j];
}
return true;
}
else return false;
}
else if(duan<k-1){ //当分的不够多时,也是算true,因为说明d太大了,所以要缩小y;
return true;
}
else return false;
}
ll bin(ll x,ll y){
while(x<y){
ll mid=x+(y-x)/2;
if(is_ok(mid)) y=mid;
else x=mid+1;
}
return x;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
memset(a,0,sizeof(a));
memset(cp,0,sizeof(cp));
tp=0;
scanf("%lld%lld",&m,&k);
for(int i=1;i<=m;i++) scanf("%lld",&a[i]);
ll sum=0,lmax=-1;
for(int i=1;i<=m;i++){
sum+=a[i];
lmax=max(lmax,a[i]);
}
ll ans=bin(lmax,sum);
ll res=0;
sort(cp,cp+tp);
for(int i=1;i<=m;i++){
if(i==cp[res]&&i==m&&res!=tp){
printf("/ %lld",a[i]);
res++;
}
else if(i!=cp[res]&&i==m){
printf("%lld",a[i]);
}
else if(i==cp[res]&&i!=m&&res!=tp){
printf("/ %lld ",a[i]);
res++;
}
else if(i!=cp[res]&&i!=m) printf("%lld ",a[i]);
}
printf("\n");
}
}
/*
1
4 4
20 100 100 200
*/