Так как я думал, что проблема была забавной, я сделал модель для поиска решений, используя программирование ограничений. Модель написана на языке моделирования под названием MiniZinc .
include "globals.mzn";
%%% Data declaration
% Number of products
int: n;
% Quantity of stock
array[1..n] of int: stock;
% Number of distinct price labels
int: m;
% Labels
array[1..m] of int: labels;
constraint assert(forall(i,j in 1..m where i < j) (labels[i] < labels[j]),
"All labels must be distinct and ordered");
% Quantity of each label
array[1..m] of int: num_labels;
% Number of precedence constraints
int: k;
% Precedence constraints
array[1..k, 1..2] of 1..n: precedences;
%%% Variables
% Price given to product i
array[1..n] of var min(labels)..max(labels): prices :: is_output;
% Objective to minimize
var int: objective :: is_output;
%%% Constraints
% Each label is used once
constraint global_cardinality_low_up_closed(prices, labels, num_labels, num_labels);
% Prices respect precedences
constraint forall(i in 1..k) (
prices[precedences[i, 1]] <= prices[precedences[i, 2]]
);
% Calculate the objective
constraint objective = sum(i in 1..n) (prices[i]*stock[i]);
%%% Find the minimal solution
solve minimize objective;
Данные по проблеме приведены в отдельном файле.
%%% Data definitions
n = 10;
stock = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
m = 10;
labels = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
num_labels = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1];
k = 1;
precedences = [| 1, 10 |];
Модель довольно наивная и прямолинейная, без излишеств. Используя серверную часть Gecode для решения примера задачи, генерируется следующий вывод (при условии, что модель находится в model.mzn, а данные в data.dzn)
$ mzn2fzn -I/usr/local/share/gecode/mznlib/ model.mzn data.dzn
$ fz -mode stat -threads 0 model.fzn
objective = 265;
prices = array1d(1..10, [1, 10, 9, 8, 7, 6, 5, 4, 3, 2]);
----------
objective = 258;
prices = array1d(1..10, [2, 10, 9, 8, 7, 6, 5, 4, 1, 3]);
----------
objective = 253;
prices = array1d(1..10, [3, 10, 9, 8, 7, 6, 5, 2, 1, 4]);
----------
objective = 250;
prices = array1d(1..10, [4, 10, 9, 8, 7, 6, 3, 2, 1, 5]);
----------
objective = 249;
prices = array1d(1..10, [5, 10, 9, 8, 7, 4, 3, 2, 1, 6]);
----------
==========
%% runtime: 0.027 (27.471000 ms)
%% solvetime: 0.027 (27.166000 ms)
%% solutions: 5
%% variables: 11
%% propagators: 3
%% propagations: 136068
%% nodes: 47341
%% failures: 23666
%% peak depth: 33
%% peak memory: 237 KB
Для более крупных задач это, конечно, намного медленнее, но модель, как правило, будет генерировать последовательно лучшие решения со временем.