题目:
题目的意思就是给出m个数,分成k组,只能连续的分成一组。求分组中和的最大值最小。
思路:二分枚举最大值,然后划分的每一组尽量接近这个枚举的值,最大值尽量小。这道题的核心部分是二分枚举,贪心主要体现在尽量靠近枚举的值
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
using namespace std;
const int maxn = 505;
long long l, r, n, group;
int a[maxn];
int vis[maxn];
bool judge(long long x) {
int k = 1, i;
long long sum = 0;
for(i=0; i<n; i++) {
if(sum + a[i] <= x) {
sum += a[i];
}else {
k++;
sum = a[i];
}
if(k>group) return false;
}
return true;
}
void print() {
memset(vis, 0, sizeof(vis));
int k = 1,i;
long long sum=0;
for(i=n-1; i>=0; i--) {
if(sum+a[i]<=l) {
sum += a[i];
}else {
k++;
sum = a[i];
vis[i] = 1;
}
}
for(i=0; i<n-1&&k<group; i++) {
if(!vis[i]) {
vis[i]=1;
k++;
}
}
for(i=0; i<n; i++) {
if(i!=n-1) {
printf("%d ", a[i]);
if(vis[i]) {
printf("/ ");
}
}
else printf("%d\n", a[i]);
}
}
int main() {
int kase;
scanf("%d", &kase);
while(kase--) {
long long sum = 0;
long long m = 0;
int i;
scanf("%d%d", &n, &group);
for(i=0; i<n; i++) {
scanf("%d", &a[i]);
sum += a[i];
m = a[i]>m?a[i]:m;
}
l=m, r=sum;
while(r>l) {
long long mid = (l+r)/2;
if(judge(mid)) {
r=mid;
}else l=mid+1;
}
print();
}
}