给定一个数组arr,长度为N且每个值都是正数,代表N个人的体重。再给定一个正数 limit,代表一艘船的载重。
以下是坐船规则:
返回如果同时让这N个人过河最少需要几条船。
首先把整个数组进行排序,若数组中出现大于limit的数字,则无法过河,直接返回-1。
普遍情况算法流程:
1.找到小于等于limit一半的数位置L,另一半指针为R= L+1。
2.从L开始和R位置的数进行配对。
2.1 如果L位置的数和R位置上的数加起来大于limit,那么R位置保持不变,L位置向左移动一位,原本L位置的数字为X类型数字。
2.2 如果L位置的数和R位置上的数加起来小于等于limit,那么移动R位置,查看R右半部分宫有几个数字和L位置数字匹配满足条件。我们就找到了一批匹配的数字,记录右部分移动了几位,左半部分也相应的移动几位。这类型的人员用√表示。
2.3 在2.2中若右半部分找不到匹配的数字,则L向左移动一位,原本L位置的数字为X类型数字。
2.4 最后结果可能分为两种情况:左侧先匹配完和右侧先匹配完。当左侧先匹配完时,右侧剩下的数字每个人一条船。当右侧先匹配完时,左侧剩下的每个人都是X类型。
3. X类型人员两人乘一艘船,√号类型人员左半部分和右半部分搭配乘一条船,右侧剩下的人员每个人乘一条船。最后的结果是这三类人员相加和。
public static int minBost(int[] arr, int limit) {if (arr == null || arr.length == 0) {return 0;}int N = arr.length;if (arr[N - 1] > limit) {return -1;}int lessR = -1;//所有人的体重都不超过limit// <= limit/2 最右的位置for (int i = N - 1; i >= 0; i--) {if (arr[i] <= (limit / 2)) {lessR = i;break;}}if (lessR == -1) {return N;}int L = lessR;int R = lessR + 1;int noUsed = 0;//画X的数量统计while (L >= 0) {int solved = 0;//此时的[L],让R画过了几个数while (R < N && arr[L] + arr[R] <= limit) {R++;solved++;}//R来到不达标的位置if (solved == 0) {noUsed++;L--;} else {//此时的[L],让R画过的solved个数L = Math.max(-1, L - solved);}}//左半区总个数 <=limit/2的区域int all = lessR + 1;//画对号的量int used = all - noUsed;// >limit/2区域中,没搞定的数量int moreUnsolved = (N - all) - used;return used + ((noUsed + 1) >> 1) + moreUnsolved;}public static void main(String[] args) {int[] arr = {1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5};int weight = 6;System.out.println(minBost(arr, weight));}
上一篇:Hygieia (Devops)开源-搭建步骤(一)
下一篇:JADE: Adaptive Differential Evolution withOptional External Archive