我想知道是否有人可以指出一种有效的方法来做到这一点:
最大化 6 行 x 10 列数组中所选元素的总和,以便在每列中选择 3 个元素,在每行中选择 5 个元素。
我看不到将分配问题(和匈牙利算法)扩展到此任务的简单方法。我们需要为我们更大的问题做数千次这样的事情,所以暴力是不可能的。
我想知道是否有人可以指出一种有效的方法来做到这一点:
最大化 6 行 x 10 列数组中所选元素的总和,以便在每列中选择 3 个元素,在每行中选择 5 个元素。
我看不到将分配问题(和匈牙利算法)扩展到此任务的简单方法。我们需要为我们更大的问题做数千次这样的事情,所以暴力是不可能的。
正如 Vaughn 所写,解决问题的一种快速简便的方法是将其转换为整数线性规划问题,然后使用众多专业求解器中的一个来求解。所以让我们开始吧!
首先,我们需要一种建模语言。我将使用 GNU 建模语言 MathProg,它与AMPL的(一个子集)非常相似。
我们问题的一般模型:(max.mod)
param rows;
param columns;
param matrix{i in 1..rows, j in 1..columns}; # the input matrix
## the variables of our problem. choose[i,j] = 1 means that we
## pick element (i,j), otherwise is choose[i,j] = 0
var choose{i in 1..rows, j in 1..columns} binary;
## the linear function we want to maximize: the sum of all the
## choosen elements in the matrix.
maximize Sum:
sum{i in 1..rows, j in 1..columns} choose[i,j] * matrix[i,j];
## first linear constraint: we have to choose exactly 3 elements for each column
subject to Cols{j in 1..columns}:
sum{i in 1..rows} choose[i,j] = 3;
## second linear constraint: we have to choose exactly 5 elements for each row
subject to Rows{i in 1..rows}:
sum{j in 1..columns} choose[i,j] = 5;
solve;
## to print the solution
printf "Solution: \n";
for{i in 1..rows}
{
for{j in 1..columns}
{
printf (if choose[i,j] = 1 then "%d " else "- "), matrix[i,j];
}
printf "\n";
}
printf "\nSum = %d", sum{i in 1..rows, j in 1..columns} choose[i,j]*matrix[i,j];
我们也需要一个数据文件:(max.dat)
param rows := 6;
param columns := 10;
param matrix :
1 2 3 4 5 6 7 8 9 10 :=
1 1 6 9 1 0 7 5 4 3 2
2 9 7 4 6 4 3 2 1 4 9
3 9 6 4 3 2 1 5 7 8 9
4 6 5 4 3 7 8 9 6 4 2
5 7 5 4 3 2 8 9 6 7 8
6 9 7 6 5 3 9 6 3 2 1;
现在我们需要一个求解器。我将在命令行中使用漂亮的GLPK(GNU 线性编程工具包),但它有一组很好的接口,可以连接到一堆编程语言。
alberto@alberto-notebook:~/Desktop$ glpsol --model max.mod --data max.dat
INTEGER OPTIMAL SOLUTION FOUND
Time used: 0.0 secs
Memory used: 0.2 Mb (235703 bytes)
Solution:
- 6 9 - - 7 5 - 3 -
9 7 - 6 4 - - - - 9
9 - - 3 - - - 7 8 9
- - 4 - 7 8 9 6 - -
- - - - - 8 9 6 7 8
9 7 6 5 3 - - - - -
Sum = 203