将m个item分配到n个box中,每个box中可存多个item,每个item只能放到一个box中。试求所有可能的解。每个Box都是一样的,所以解没有顺序之分。也就是说2,3,5 和 2 ,5,3被认为是同样的解。
给出指定的m(m>=0)和n(n >0),请给出所有的解。
这个题可以按照分治递归的思路求解。当box 数量是1或者2时很容易求解。 当 box =1 时直接返回m就是所求解;当 box=2时,可以把m(例如m=5)分成两步进行求解,那么可能的组合为 (0<=i<=m/2, m-i)
(0 5)
(1 4)
(2 3)
当box >2时,可以把box按照box/2取中分解成两部分,同时按照上述分解m(Item数量)的方式将m进行分解。如此递归。
package com.tr.algorithm.example.item4box;
public class IntelliItemDist {
public IntelliItemDist(){
super();
}
/**
* 递归分配item 到 box 中。
* @param 待分发的item数量
* @param 可用的box数量
* @return 返回可用方案。
*/
private int[][] dispatch(int item,int box){
int[][] m = new int[0][0];
if (box == 1){
m = new int[1][1];
m[0] = new int[]{item};
}else if (box ==2){
int middleItem = item/2;
m = new int[middleItem+1][2];
for (int i=0;i< m.length;i++){
m[i] = new int[]{i,item-i};
}
}else if (box > 2){
int middleBox = box/2; //取box中数,
int middleItem = item/2;//取item中数
for (int i =0 ; i <= middleItem;i++){
int[][] left = dispatch(i,middleBox);
int[][] right= dispatch(item-i,box-middleBox);
int[][] lr = crossMerge(left,right);
m = appendMerge(m,lr);
}
}
return m;
}
/**
* 将两个二维数组left[m][n],right[j][k]合并成m[m*j][]数组。
*/
private int[][] crossMerge(int[][] left,int[][] right){
int[][] m = new int[left.length * right.length][];
int row = 0;
for (int i=0;i< left.length;i++){
for (int j=0;j< right.length;j++){
int[] l = left[i];
int[] r = right[j];
m[row] = merge(l,r);
row++;
}
}
return m;
}
/**
* 将两个二维数组left[m][n],right[j][k]合并成m[m+j][]数组。
*/
private int[][] appendMerge(int[][] left,int[][] right){
int[][] m = new int[left.length + right.length][];
for (int i=0;i< left.length;i++){
m[i] = left[i];
}
for (int i=left.length;i< m.length;i++){
m[i] = right[i - left.length];
}
return m;
}
/**
* 将两个一维数组left[m],right[j]合并成m[m+j]数组。
*/
private int[] merge(int[] left,int[] right){
int[] m = new int[left.length + right.length];
System.arraycopy(left,0,m,0,left.length);
System.arraycopy(right, 0, m, left.length, right.length);
return m;
}
public static void main (String[] args){
int item = 5,box=4;
IntelliItemDist bpu = new IntelliItemDist();
int[][] solution = bpu.dispatch(item,box);
for (int i = 0;i<solution.length;i++){
for (int j = 0;j<solution[i].length;j++){
System.out.print(solution[i][j] + " ");
}
System.out.println();
}
}
}
方案输出如下:
0 0 0 5
0 0 1 4
0 0 2 3
0 1 0 4
0 1 1 3
0 1 2 2
0 2 0 3
0 2 1 2
1 1 0 3
1 1 1 2
目前改方法存在重复解决方案,原因是子问题不能互相独立。有时间再解。也请高手不吝赐教。