多重分配/矩阵最大化

Posted

技术标签:

【中文标题】多重分配/矩阵最大化【英文标题】:Multiple Assignment / Matrix Maximization 【发布时间】:2012-11-17 14:40:22 【问题描述】:

我想知道是否有人可以指出一种有效的方法来做到这一点:

最大化 6 行 x 10 列数组中所选元素的总和,使得每列恰好选择 3 个元素,每行选择 5 个元素。

我看不到将分配问题(和匈牙利算法)扩展到此任务的简单方法。我们需要为更大的问题做数千次这样的操作,所以暴力是不可能的。

【问题讨论】:

这类问题如果想在一般情况下最优解,一般都是NP。 我明白了。您能否指出一个您已经解决的“此类问题”? 可以表示为整数规划问题:en.wikipedia.org/wiki/Integer_programming。在这种情况下,变量是每个单元格是否被选中,因此是一个 0-1 整数规划问题。 【参考方案1】:

正如 Vaughn 所写,解决问题的一种快速简便的方法是将其转换为 Integer Linear Programming 问题,然后使用众多专业求解器之一来解决它。所以,让我们开始吧!

建模

首先,我们需要一种建模语言。我将使用 GNU 建模语言 MathProg,它与 AMPL 的(一个子集)非常相似。

我们问题的一般模型:(max.mod)

param rows;
param columns;
param matrixi 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 choosei 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:
    sumi 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 Colsj in 1..columns:
    sumi in 1..rows choose[i,j] = 3;

## second linear constraint: we have to choose exactly 5 elements for each row
subject to Rowsi in 1..rows:
    sumj in 1..columns choose[i,j] = 5;

solve;

## to print the solution
printf "Solution: \n";
fori in 1..rows

    forj in 1..columns
    
        printf (if choose[i,j] = 1 then "%d " else "- "), matrix[i,j];
    
    printf "\n";

printf "\nSum = %d", sumi 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

【讨论】:

感谢您提供此解决方案!实际上,我们刚刚对匈牙利算法进行了修改以解决我们的问题,但我会检查每个算法的效率并在某个时候报告。 @nair.ashvin 你检查过每种方法的效率吗? 不,我们最终没有使用上面的线性规划方法。

以上是关于多重分配/矩阵最大化的主要内容,如果未能解决你的问题,请参考以下文章

hihoCoder 1393 网络流三·二分图多重匹配(Dinic求二分图最大多重匹配)

求多重邻接表的迪杰斯特拉算法

动画库中的断言错误:已注册的矩阵数等于创建时设置的最大数

图的存储邻接矩阵邻接表十字链表以及邻接多重表相关方法(C语言)

文本左右对齐(字符串模拟)螺旋矩阵 II(数组矩阵)二叉树中的最大路径和(树深度优先搜索)

BZOJ5010: [Fjoi2017]矩阵填数