**
【挑战程序设计】利用二分搜索计算最优解问题 JAVA实现
**
题目要求
传送带依次送来了重量分别为wi(i = 0, 1,…, n - 1)的n个货物。现在要将这些货物装到k辆卡车上。每辆卡车可装载的货物数大于等于0,但货物重量总和不得超过卡车的最大运载量P。所有卡车的最大运载量P一致。请编写一个程序,输入__n,k,w[i]__求出装载全部货物所需的最大运载量P的最小值。
输入:
第一行输入整数n和k,用空格隔开。接下来n行输入n个整数wi,每个数占一行。
输出: 输出P的最小值,占1行。
限制:
1≤n≤100000
1≤k≤100000
1≤wi≤10000
输入示例
输出示例
这里大概的思路是有一个checkP方法,返回值为j(货车最大运载量为P时装的货物数),假设将P放在一个很大的集合里,现在不知道P的值,利用二分法得到mid,利用check(mid)方法不断缩小P的范围,判断条件是while(right-left)>1,直到找到最小的P,也就是P,返回right(right就是满足条件的最小P),因为最后的结果一定是v(k辆最大运载量为P的货车能装的货物数)>=n,若小于n,肯定不满足题目(货车装不下)。则一定返回的是right所记录的mid值。
具体代码
package optimalSolution;
public class Method {
//k辆最大运载量为P的货车能装多少个货物
public int checkP(int k,int P,int w[],int n) {
int sum;
int j = 0;
for (int i = 0; i < k; i++) {
sum = 0;
while(sum+w[j]<=P) { //当sum加下一个货物重量时,若超过P,则返回j,j为货物个数,从0开始
sum+=w[j];
j++;
if(j==n) return j; //若P过大的话,可能发生这种情况,一辆货车可以装所有的货物,返回j=n
}
}
return j; //j从0开始,因此不需要j-1
}
//利用二分搜索查找P的最小值
public int findP(int k,int w[],int n) {
int left = 0; //P集合的最左侧
int right = 10000*10000; //P集合的最右侧,最大货物数*最大货车数,注意看题目的限制
int mid = 0;
int v = 0;
while(right-left>1) {
mid = (left+right)/2;
v = checkP(k,mid,w,n); //v记录了一个货车可以装多少个货物
if(v>=n) right = mid;
else left =mid;
}
return right;
}
}
package optimalSolution;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// 二分搜索计算最优解
Scanner scan = new Scanner(System.in);
System.out.println("请输入:");
int n = scan.nextInt(); //n个货物
int k = scan.nextInt(); //k个货车
int[] w = new int[n]; //wi不同重量的货物数组
Method m = new Method();
for (int i = 0; i < n; i++) {
w[i] = scan.nextInt();
}
System.out.println(m.findP(k, w, n));
}
}