我正在整理一个Java小程序,以便在工作中更快,更高效地完成任务。
用户定义需要拆分项目列表的三个组的大小。列表中的每个项目根据放入的三个组中的哪个组具有不同的值。小程序需要显示哪些组合具有最高总值。
实施例: 带列的二维整数数组;项目编号,组1中的值,组2中的值和组3中的值。
16 2 2 5
19 6 0 3
24 1 4 4
25 4 2 3
27 4 2 3
29 3 3 3
31 5 3 1
32 5 2 2
用户定义组1有3个插槽,组2有3个插槽,组3有2个插槽。
小程序应按以下特定顺序显示以下解决方案
Group 1: 19, 31, 32
Group 2: 24, 27, 29
Group 3: 16, 25
OR
Group 1: 19, 27, 32
Group 2: 24, 29, 31
Group 3: 16, 25
OR
Group 1: 19, 31, 32
Group 2: 24, 25, 29
Group 3: 16, 27
OR
Group 1: 19, 25, 32
Group 2: 24, 29, 31
Group 3: 16, 27
我可以通过所有可能的命令管理一种不那么有效的方式运行数组,但它会产生重复的解决方案(即16,25和25,16)。我确信有一种方法可以总结所有可能的组合,甚至不需要改组阵列。我此刻无法绕过它。如果你们有任何方法,我会非常感激。
答案 0 :(得分:0)
已更新:使用动态编程的新方法
(旧的:)
我认为我们可以使用贪婪的方法。这个想法是:
为了实现上述想法,我们可以使用数组used[]
来识别是否使用了一个项目(已经放入一个组),三个最大堆来表示表中的三个值列。堆元素就像(值是键)。假设三个堆是H[0]
,H[1]
和H[2]
。算法是这样的:
Init bool array `used[n]` to all false
Init heap array `H[3]`
Init int array `capacity[3]` to required group sizes
for(int i from 0 to n-1){
int v = -1, heap_number, item_number;
for(int j from 0 to 2){
if(capacity[j] == 0){
continue;
}
while(used[H[j].top().item_number]){
H[j].pop();
}
if(H[j].top().value > v){
v = H[j].top().value;
heap_number = j;
item_number = H[j].top().item_number;
}
}
Assign Item item_number to Group heap_number
used[item_number] = true;
capacity[heap_number]--;
}
这是我的新方法,一种动态编程方法:
f[i][j][k]
表示组1,2和3的解决方案,每个组分别留有i,j和k个槽。解决方案是三个列表,记录从项目到组的分配。假设a = i + j + k
。f[i][j][k] = max{f[i-1][j][k] + Item[a].value_1, f[i][j-1][k] + Item[a].value_2, f[i][j][k-1] + Item[a].value_3}
。f[0][0][0] = 0
。f[group_1_size][group_2_size][group_3_size]
。答案 1 :(得分:0)
我无法想出一个解决方案,但回答你的问题 - 关于运行所有可能的总和 - 你可以使用递归。
// @row - currently processed row
// @g1, g2, g3 - arrays with numbers of rows put in respective group
// @options - for results
// @rows - source array
void PROCESS_ROW(int row, int[] g1, int[] g2, int[] g3, int[][][][] options, rows) {
if (row >= rows.length) {
// Recursion ended, collecting generated distribution
options[].push_back(new int[3][][]);
options[last][0] = g1.clone();
options[last][1] = g2.clone();
options[last][2] = g3.clone();
return;
}
// Trying to put row in each group consequently
if (g1.length < g1_slots) {
g1.push_back(row);
PROCESS_ROW(row + 1, g1, g2, g3, options, rows);
g1.pop_back();
}
if (g2.length < g2_slots) {
g2.push_back(row);
PROCESS_ROW(row + 1, g1, g2, g3, options, rows);
g2.pop_back();
}
if (g3.length < g3_slots) {
g3.push_back(row);
PROCESS_ROW(row + 1, g1, g2, g3, options, rows);
g3.pop_back();
}
}
int[][] rows;
// .. fill
int[][][][] options;
PROCESS_ROW(0, new int[], new int[], new int[], options, rows);
// now options contains all possible groupings
实际上,这段代码不是Java,因此需要进行调整。此外,还必须传递g1_slots等作为参数,但它的详细信息。这个想法是可以理解的。此外,很有可能在第一if
部分中包括更强的处理,计算总和并存储最高的一个以及可能的组合。每次遇到更高的总和时清除数组
当然,这个解决方案意味着行有数字0,1,2 ..,16,19,25的内容......所以,应该再次调整这个方面,使用Map rows
而不是数组。但正如我所说,它的细节。