P1182 数列分段 Section II - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
这个题目有点小坑。
我们使用二分答案,记住最小值选取我们数组里的最大值,要不然就要在二分的检验函数里建一个判断(就是不允许单个数值大于我们二分的数值),此题我们二分答案,二分得到值后,我们对数组里的数分组
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.math.MathContext;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeMap;
import java.util.TreeSet;
public class Main {
public static void main(String[] args) throws NumberFormatException, IOException {
Scanner sc=new Scanner(System.in);
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String[] aStrings=br.readLine().split(" ");
aa=Integer.parseInt(aStrings[0]);
bb=Integer.parseInt(aStrings[1]);
String[] bStrings=br.readLine().split(" ");
int a;
long b=0;
long c=0;
dp=new int[aa];
for(a=0;a<aa;a++) {
dp[a]=Integer.parseInt(bStrings[a]);
c=Math.max(c, dp[a]);//左边界选取数组里最大的数
b=b+dp[a];//右边界累加和
}
long answer=0;
while(c<=b) {
long mid=(c+b)>>>1;//二分答案
if(check(mid)==0) {
c=mid+1;
//System.out.println("AA"+mid);
}
else {
answer=mid;
//System.out.println(answer);
b=mid-1;
}
}
System.out.println(answer);
}
public static int[] dp;
public static int aa;
public static int bb;//最多分几组
public static int check(long a) {
int b;
int c=1;
long d=0;
for(b=0;b<aa;b++) {
if(dp[b]>a) {//如果单个数字大于我们二分的值,结束
return 0;
}
d=d+dp[b];
if(d>a) {
c++;
d=dp[b];
}
}
if(c>bb) {
return 0;
}
else {
return 1;
}
}
}
本题注意,我们使用最佳情况来分组,可能我们得最佳情况比标准要小。举个例子
5个数分5个组1 3 3 3 4当我们每组之和为4时分为4个组小于5,当我们变为3时,最优分组会无法fen因为4大于3,但是当我们为4时,我们不采用最优分组,可以得到5组。
所以我们合并情况。把等于和小于合成一组,来不断改变值