Java 在n个箱子中分配物品的i号,其中每个箱子具有不同的容量等级c1、c2
我必须分发我的文件。n个箱子中的物品数量,每个箱子具有不同的容量等级c1、c2。。。中国。我想按容量的比例分配物品。因此,容量最高的盒子将包含最多的物品,反之亦然。容量可能不是按升序排列的。容量也可以是0。此外,如果项目数量超过总容量,则将所有箱子装满,直至其最大容量 这个问题已经有解决办法了吗 因为我写了下面的算法。但它的效率不高。同时,它在以下输入处无限循环。因为-2的差异从未解决过。因此,在其他用例中,它也会出现故障Java 在n个箱子中分配物品的i号,其中每个箱子具有不同的容量等级c1、c2,java,algorithm,Java,Algorithm,我必须分发我的文件。n个箱子中的物品数量,每个箱子具有不同的容量等级c1、c2。。。中国。我想按容量的比例分配物品。因此,容量最高的盒子将包含最多的物品,反之亦然。容量可能不是按升序排列的。容量也可以是0。此外,如果项目数量超过总容量,则将所有箱子装满,直至其最大容量 这个问题已经有解决办法了吗 因为我写了下面的算法。但它的效率不高。同时,它在以下输入处无限循环。因为-2的差异从未解决过。因此,在其他用例中,它也会出现故障 int[] arrCap = {1,1,0,1,1}; new Dist
int[] arrCap = {1,1,0,1,1};
new Distributor(arrCap, 2).distribute();
import java.util.Arrays;
public class Distributor {
/** Capacity of each box */
private final int[] boxCapacity;
/** Total no. of boxes */
private final int NO_OF_BOXES;
/** Total no. of items that are to be distributed into each box */
private final int NO_OF_ITEMS;
/** Total capacity available. */
private long totalCapacity;
/** Fractionally ratio distributed items according to capacity */
private float[] fractionalRatios;
/** Ratio distributed items according to capacity */
private int[] ratioDistributedCapacity;
/** Sorted Rank of distributed items in ascending / descending order */
private int[] rankIndex;
/** The difference between the totalCapacity and total of ratioDistributedCapacity */
private int difference;
/**
* Validates the total capacity and no. of items to be distributed.
* Initializes the distributor with box capacity array, no of items.
* Implicitly calculates no. of boxes as length of box capacity array.
* @param boxCapacity Array of capacity of each box.
* @param noOfItems No. of Items to be distributed.
*/
public Distributor(int[] boxCapacity, int noOfItems) {
calculateBoxes(boxCapacity);
this.boxCapacity = boxCapacity;
this.NO_OF_ITEMS = noOfItems;
NO_OF_BOXES = boxCapacity.length;
ratioDistributedCapacity = new int[NO_OF_BOXES];
rankIndex = new int[NO_OF_BOXES];
}
/**
* Calculates the ratio into which the items are to be distributed.
* Actually assigns the items into each box according to the ratio.
* @return Array of int[] containing ratio distributed items according to its capacity.
*/
public int[] distribute() {
// If NO_OF_ITEMS to be distributed is more than totalCapacity then distribute all the items upto full capacity
if (NO_OF_ITEMS >= totalCapacity) {
ratioDistributedCapacity = boxCapacity;
} else {
calculateRatioAndDistribute();
}
return ratioDistributedCapacity;
}
/**
* Calculates the ratio & distributes the items according to the capacity.
*/
private void calculateRatioAndDistribute() {
fractionalRatios = new float[NO_OF_BOXES];
for (int i=0; i<NO_OF_BOXES; i++) {
fractionalRatios[i] = ((float) boxCapacity[i] * (float) NO_OF_ITEMS) / (float) totalCapacity;
ratioDistributedCapacity[i] = Math.round(fractionalRatios[i]);
}
print(fractionalRatios);
print(ratioDistributedCapacity);
// keep redistributing the difference until its not 0
while ((difference = rectifyAndGetDistributionResult()) != 0) {
redistribute();
}
print(ratioDistributedCapacity);
}
/**
* Redistributes the difference between the already allotted ratioDistributedCapacity array.
* Also if the difference is 0 that means everything is already settled.
* No more further need to do anything.
* @param difference the difference that needs to be settled to equal the no. of items with total distributed items.
*/
private void redistribute() {
if (difference > 0) {
// calculate distribution ranks in ascending order
calculateDistributionRanks(true); // orderDescending = true
// eliminate the invalid ranks from rankIndex
eliminateInvalidRanks();
// In case all the ranks have become invalid. In this case the rankIndex will be empty.
// So we need to re calculate the distribution ranks in opposite order.
if (rankIndex.length == 0) {
calculateDistributionRanks(false); // orderDescending = false
}
} else if (difference < 0) {
// calculate distribution ranks in descending order
calculateDistributionRanks(false); // orderDescending = false
// eliminate the invalid ranks from rankIndex
eliminateInvalidRanks();
// In case all the ranks have become invalid. In this case the rankIndex will be empty.
// So we need to re calculate the distribution ranks in opposite order.
if (rankIndex.length == 0) {
calculateDistributionRanks(true); // orderDescending = true
}
}
// add / substract 1 from the ratioDistributedCapacity of the element in order of the rankIndex
// according to negative / positive difference until the difference becomes 0.
final int len = rankIndex.length;
for (int i=0; i<len; i++) {
if (difference == 0) {
break;
} else if (difference > 0) {
ratioDistributedCapacity[ rankIndex[i] ]++;
difference--;
} else if (difference < 0) {
ratioDistributedCapacity[ rankIndex[i] ]--;
difference++;
}
}
}
/**
* If the value of any ratioDistributedCapacity element exceeds its capacity or is less than 0,
* revert it with its initial capacity value.
*/
private void rectify() {
for (int i=0; i<NO_OF_BOXES; i++) {
ratioDistributedCapacity[i] = ((ratioDistributedCapacity[i] > boxCapacity[i]) || (ratioDistributedCapacity[i] < 0)) ? boxCapacity[i] : ratioDistributedCapacity[i];
}
}
/**
* Calculates the distribution ranks i.e. indexes of fractionalRatios array.
* Sorts them into ascending or descending order.
* @param orderDesc Sort order. true for descending and false for ascending.
*/
private void calculateDistributionRanks(boolean orderDesc) {
// Copy fractionalRatios array to another tmp array. Note:- Use fractionalRatios so ranking can be more accurate.
float[] tmp = Arrays.copyOf(fractionalRatios, NO_OF_BOXES);
// Sort the array in ascending order
Arrays.sort(tmp);
// re-initialize the rankIndex array
rankIndex = new int[NO_OF_BOXES];
for (int i=0; i<NO_OF_BOXES; i++) {
innerLoop: for (int j=0; j<NO_OF_BOXES; j++) {
if (tmp[i] == fractionalRatios[j]) {
// Store the array index of unsorted array if its value matches value of sorted array.
rankIndex[i] = j;
break innerLoop;
}
}
}
// reverse the rank array if orderDesc flag is true
if (orderDesc) reverse();
print(rankIndex);
}
/**
* Remove the indexes from rank which are already full or equal to 0
* or are not eligible for increment / decrement operation.
*/
private void eliminateInvalidRanks() {
final int len = rankIndex.length;
int invalidRankCount = 0;
final int markInvalidRank = -1;
for (int i = 0; i < len; i++) {
if (boxCapacity[rankIndex[i]] <= 0) {
// mark this rank number as invalid, for removal
rankIndex[i] = markInvalidRank;
invalidRankCount++;
continue;
}
if (difference > 0) {
if ((ratioDistributedCapacity[rankIndex[i]] >= boxCapacity[rankIndex[i]])) {
// mark this rank number as invalid, for removal
rankIndex[i] = markInvalidRank;
invalidRankCount++;
continue;
}
} else if (difference < 0) {
if (ratioDistributedCapacity[rankIndex[i]] <= 0) {
// mark this rank number as invalid, for removal
rankIndex[i] = markInvalidRank;
invalidRankCount++;
continue;
}
}
}
int[] tmp = new int[(len - invalidRankCount)];
int j = 0;
for (int i = 0; i < len; i++) {
if (rankIndex[i] != markInvalidRank) {
tmp[j++] = rankIndex[i];
}
}
rankIndex = tmp;
print(rankIndex);
}
/**
* Rectifies the elements value inside ratioDistributedCapacity.
* Calculates the total of already distributed items.
* @return Difference between total distributed items and initial no. of items that were to be distributed.
*/
private int rectifyAndGetDistributionResult() {
rectify();
int remaining = NO_OF_ITEMS;
for (int tmp: ratioDistributedCapacity) {
remaining -= tmp;
}
return remaining;
}
/**
* Validates the capacity array and no. of items to be distributed.
* @param arrCapacity Array of capacity of each box.
*/
private void calculateBoxes(int[] arrCapacity) {
for (int i: arrCapacity) {
totalCapacity += i;
}
}
/**
* Prints the array elements and the total of the elements within it.
* @param x
*/
private void print(int[] x) {
final int len = x.length;
final StringBuilder sb = new StringBuilder("");
for (int i=0; i<len; i++) {
sb.append(x[i]).append(", ");
}
System.out.println(sb.toString());
}
/**
* Prints the array elements and the total of the elements within it.
* @param x
*/
private void print(float[] x) {
final int len = x.length;
final StringBuilder sb = new StringBuilder("");
for (int i=0; i<len; i++) {
sb.append(x[i]).append(", ");
}
System.out.println(sb.toString());
}
private void reverse() {
final int len = rankIndex.length;
for (int i=0; i < (len/2); i++) {
rankIndex[i] += rankIndex[len - 1 - i]; // a = a+b
rankIndex[len - 1 - i] = rankIndex[i] - rankIndex[len - 1 - i]; // b = a-b
rankIndex[i] -= rankIndex[len - 1 - i]; // a = a-b
}
}
}
int[]arrCap={1,1,0,1,1};
新分配器(arrCap,2)。distribute();
导入java.util.array;
公共类分发服务器{
/**每个箱子的容量*/
私人最终通行能力;
/**箱子总数*/
专用最终整备箱编号;
/**要分发到每个箱子中的项目总数*/
项目的专用最终整数编号;
/**总可用容量*/
私人长期总容量;
/**根据容量对分配的项目进行分数比率*/
私人浮动利率;
/**按容量分配的项目比率*/
私人int[]比例分配容量;
/**按升序/降序排列的已分发项目的排序*/
私人内特[]兰金德克斯;
/**总容量与比率分配容量之差*/
私人智力差异;
/**
*验证要分发的项目的总容量和数量。
*使用盒子容量数组初始化分发服务器,项目数为。
*隐式计算盒子数量作为盒子容量数组的长度。
*@param-boxCapacity每个盒子的容量数组。
*@param noOfItems要分发的项目数。
*/
公共分销商(国际[]箱容量,国际noOfItems){
计算箱(箱容量);
this.boxCapacity=boxCapacity;
此项的数量=不适用项;
箱的数量=箱容量.length;
ratioDistributedCapacity=新的整数[NO_OF_Box];
rankIndex=新整数[框的数量];
}
/**
*计算项目要分配到的比率。
*根据比率将项目实际分配到每个框中。
*@return int[]数组,包含按容量分配的比率项。
*/
公共int[]分发(){
//如果要分配的项目中没有超过总容量的项目,则将所有项目分配到最大容量
if(无项目>=总容量){
比率分配容量=箱容量;
}否则{
计算和分配();
}
收益率分布容量;
}
/**
*计算比率并根据容量分配项目。
*/
私有void calculateRatioAndDistribute(){
分馏率=新浮点数[无浮点数];
对于(int i=0;i 0){
//按升序计算分布等级
calculateDistributionRanks(true);//orderDescending=true
//从rankIndex中删除无效列组
消除不合格品();
//如果所有等级都无效,则rankIndex将为空。
//因此,我们需要按相反的顺序重新计算分布等级。
如果(rankIndex.length==0){
calculateDistributionRanks(false);//orderDescending=false
}
}否则如果(差异<0){
//按降序计算分发级别
calculateDistributionRanks(false);//orderDescending=false
//从rankIndex中删除无效列组
消除不合格品();
//如果所有等级都无效,则rankIndex将为空。
//因此,我们需要按相反的顺序重新计算分布等级。
如果(rankIndex.length==0){
calculateDistributionRanks(true);//orderDescending=true
}
}
//按照rankIndex的顺序,从元素的ratioDistributedCapacity中添加/减去1
//根据负/正差值,直到差值变为0。
最终整数长度=rankIndex.长度;
对于(int i=0;i 0){
比率分配容量[rankIndex[i]]++;
差异--;
}否则如果(差异<0){
比率分配容量[rankIndex[i]]-;
差异++;
}
}
}
/**
*如果任何ratioDistributedCapacity元素的值超过其容量或小于0,
*将其还原为初始容量值。
*/
私人机构{
对于(int i=0;i boxCapacity[i])| |(ratioDistributedCapacity[i]<0))?boxCapacity[i]:ratioDistributedCapacity[i];
}
}
/**
*计算分布等级,即分数比率数组的索引。
*将它们按升序或降序排序。
*@param orderDesc排序顺序。下降为true,上升为false。
*/
私有void calculateDistributionRanks(布尔orderDesc){
//将分馏比率数组复制到另一个tmp数组。注意:-使用分馏比率以便排名更准确。
float[]tmp=Arrays.copyOf(分数比率,无方框);
//按升序对数组排序
数组排序(tmp);
//重新初始化rankIndex数组
rankIndex=新整数[框的数量];
对于(inti=0;i,我想到了两种方法
最佳舍入
把这个问题当作一个最优的取整问题来处理
static int[] distribute(int[] boxes, int items) {
int[] result = new int[boxes.length];
int sumSoFar = 0;
int totalCapacity = 0;
for (int box : boxes) {
totalCapacity += box;
}
float R = (float) items / totalCapacity;
for (int i = 0; i < boxes.length - 1; i++) {
int box = boxes[i];
result[i] = Math.round(R * box);
sumSoFar += result[i];
}
result[boxes.length - 1] = items - sumSoFar;
return result;
}
System.out.println(Arrays.toString(distribute(new int[]{1, 2}, 10)));
System.out.println(Arrays.toString(distribute(new int[]{4, 12}, 8)));
[3, 7]
[2, 6]