这种题,一看就是二分,他要让前面最小,那就从后往前划分.
关键是二分还得分好多种。推荐博客
#include<bits/stdc++.h>
using namespace std;
int n,m,a[510];
long long sum;
bool flag[510];
void init(){
sum=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
sum+=a[i];
}
}
bool judge(long long lmt){
memset(flag,0,sizeof(flag));
int cnt=m;
long long now=0;
for(int i=n;i>=1;i--){
if(now+a[i]>lmt||i<cnt){ //只要人不完,只是书写完了,那也返回true,因为二分那边返回true一直往左边继续寻找最优解。
now=a[i];
flag[i]=1;
cnt--;
if(cnt==0) return false;
}
else now+=a[i];
}
return true;
}
void work(){
long long ans,l=0,r=sum,mid;
for(int i=1;i<=n;i++){
if(l<a[i]) l=a[i];
}
while(l<=r){ //二分写法看我上边推荐的那个博客,讲的很清楚。
mid=l+r>>1;
if(judge(mid)) ans=mid,r=mid-1;
else l=mid+1;
}
judge(ans);
for(int i=1;i<=n;i++){
printf("%d",a[i]);
if(i<n) printf(" ");
if(flag[i]) printf("/ ");
}
printf("\n");
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
init();
work();
}
return 0;
}