版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/PR_sc/article/details/77100197
题目链接
题意把一个包含m个正整数的序列划分成k 个非空的连续子序列,使得每一个正整数都恰好属于一个序列。设第i个序列的各数之和为S(i),你的任务是让所有S(i)的最大值尽量小。如果有多种解,S(1)尽量小,如果仍有多种解,S(2)尽量小。以此类推。
分析 二分查找。 在序列最大值和序列各数之和之间找一个数x,可以满足S(i)均不超过x 且序列数为k。
#include<bits/stdc++.h>
using namespace std;
int s[505],a[505],m,k,t;
int judge(int x){
int num=1,arr=0;
for(int i=0;i<m;i++){
if(a[i]+arr<=x) arr+=a[i];
else {num++; arr=a[i];}
}
return num;
}
void p(long long int n){
long long arr=0;
int buf=k;
memset(s,0,sizeof(s));
for(int i=m-1;i>=0;i--){
if(arr+a[i]>n || i+1<buf) {
s[i]=1;
buf--;
arr=a[i];
}
else arr+=a[i];
}
for(int i=0;i<m-1;i++){
cout<<a[i]<<" ";
if(s[i]) cout<<"/ ";
}
cout<<a[m-1]<<endl;
}
int main (void){
ios::sync_with_stdio(false);
cin>>t;
while(t--){
cin>>m>>k;
long long sum=0;
int maxc=0;
for(int i=0;i<m;i++){
cin>>a[i];
sum+=a[i];
maxc=max(maxc,a[i]);
}
long long low=maxc,high=sum,mid;
while(high-low>1e-8){
mid=(high-low)/2+low;
if(judge(mid)<=k) high=mid;
else low=mid+1;
}
p(low);
}
return 0;
}
总结 刚开始还被这个题目吓到了 感觉好复杂啊 想出思路后又觉得不难 hhhh