在求解器内部,从基于 IntVar 的数组中获取值的方法是使用MakeElement()
函数,在本例中是函数的2d 版本。
这样,您可以从矩阵中获取特定值,但不能获取基于两个 IntVar 的范围(例如矩形的 x - dx)。要完成范围部分,您可以使用循环和 aConditionalExpression()
来确定指定值是否在范围内。
例如,在一维数组中,为了从 中获取元素data
,位置x
tox + dx
将如下所示
int[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
IntVar x = solver.MakeIntVar(0, data.Length - 1);
IntVar dx = solver.MakeIntVar(1, data.Length);
solver.Add(x + dx <= data.Length);
IntVarVector range = new IntVarVector();
for (int i = 0; i < dx.Max(); i++)
{
range.Add(solver.MakeConditionalExpression((x + i < x + dx).Var() , solver.MakeElement(data, (x + i).Var()), 0).Var());
}
solver.Add(range.ToArray().Sum() <= 10);
如果是二维数组(如问题所示),那么您只需遍历两个维度。唯一的区别是 2d 版本MakeElement()
接受一个IndexEvaluator2
项目(LongLongToLong
在 C# 中),因此您必须创建自己的类来继承LongLongToLong
和覆盖该Run()
函数。
class DataValues: LongLongToLong
{
private int[,] _data;
private int _rows;
private int _cols;
public DataValues(int[,] data, int rows, int cols)
{
_rows = rows;
_cols = cols;
_data = data;
}
public override long Run(long arg0, long arg1)
{
if (arg0 >= _rows || arg1 >= _cols)
return 0;
return _data[arg0, arg1];
}
}
这个类的唯一问题是它可以从数组中请求一个值,所以我们必须自己处理它if (arg0 >= _rows || arg1 >= _cols)
。
PS我不知道这是否是实现它的最佳方法,但这是我能想到的最好的方法,因为我在网上找不到类似的东西。