这是我的问题:
示例:
我们有3天的时间来分发产品。 A公司的产品:a,a,a,a,a。 B公司产品:b,b,b。 C公司产品:c,c
公平分配 [AAB,AABC,ABC]
分发无效: [AABC,AABC,AB] 因为第1天有4个产品,第3天有2个产品(差异> 1)
分发无效: [ABC,AABC,AAB] 因为在第1天有一个产品A,在第2天有2个产品A,所以产品A的分配不是不减少
修改 如果有案例无法公平分配,请提供简短描述,我会接受答案
答案 0 :(得分:2)
Gareth Rees对djna答案的评论是正确的 - 以下反例是无法解决的:
我使用以下最愚蠢的暴力Perl程序对其进行了测试(虽然效率非常低,但在一秒钟内完成得非常好):
my ($na, $nb) = (7, 5);
for (my $a1 = 0; $a1 <= $na; ++$a1) {
for (my $a2 = 0; $a2 <= $na - $a1; ++$a2) {
my $a3 = $na - $a1 - $a2;
for (my $b1 = 0; $b1 <= $nb; ++$b1) {
for (my $b2 = 0; $b2 <= $nb - $b1; ++$b2) {
my $b3 = $nb - $b1 - $b2;
if ($a1 >= $a2 && $a2 >= $a3 || $a1 == 0 && $a2 >= $a3 || $a1 == 0 && $a2 == 0) {
if ($b1 >= $b2 && $b2 >= $b3 || $b1 == 0 && $b2 >= $b3 || $b1 == 0 && $b2 == 0) {
if (max($a1 + $b1, $a2 + $b2, $a3 + $b3) - min($a1 + $b1, $a2 + $b2, $a3 + $b3) <= 1) {
print "Success! ($a1,$a2,$a3), ($b1,$b2,$b3)\n";
}
}
}
}
}
}
}
请查看并确认我没有犯过任何愚蠢的错误。 (为简洁起见,我省略了max()
和min()
- 他们只是做了你期望的事情。)
答案 1 :(得分:2)
由于我认为这个问题很有趣,我使用MiniZinc做了一个寻找解决方案的模型。使用Gecode后端,初始示例显示在大约1.6毫秒内有20个解决方案。
include "globals.mzn";
%%% Data
% Number of companies
int: n = 3;
% Number of products per company
array[1..n] of int: np = [5, 3, 2];
% Number of days
int: k = 3;
%%% Computed values
% Total number of products
int: totalnp = sum(np);
% Offsets into products array to get single companys products
% (shifted cumulative sum).
array[1..n] of int: offset = [sum([np[j] | j in 1..i-1])
| i in 1..n];
%%% Predicates
predicate fair(array[int] of var int: x) =
let { var int: low,
var int: high
} in
minimum(low, x) /\
maximum(high, x) /\
high-low <= 1;
predicate decreasing_except_0(array[int] of var int: x) =
forall(i in 1..length(x)-1) (
(x[i] == 0) \/
(x[i] >= x[i+1])
);
predicate consecutive(array[int] of var int: x) =
forall(i in 1..length(x)-1) (
(x[i] == x[i+1]) \/
(x[i] == x[i+1]-1)
);
%%% Variables
% Day of production for all products from all companies
array[1..totalnp] of var 1..k: products
:: is_output;
% total number of products per day
array[1..k] of var 1..totalnp: productsperday
:: is_output;
%%% Constraints
constraint global_cardinality(products, productsperday);
constraint fair(productsperday);
constraint
forall(i in 1..n) (
let {
% Products produced by company i
array[1..np[i]] of var int: pi
= [products[j] |
j in 1+offset[i]..1+offset[i]+np[i]-1],
% Products per day by company i
array[1..k] of var 0..np[i]: ppdi
} in
consecutive(pi) /\
global_cardinality(pi, ppdi) /\
decreasing_except_0(ppdi)
);
%%% Find a solution, default search strategy
solve satisfy;
谓词decreasing_except_0
和consecutive
都很天真,并且有很大的分解。为了解决更大的实例,可能应该用更智能的变体替换它们(例如使用常规约束)。
答案 2 :(得分:1)
已经表明,第4点和第5点是不相容的:
|C(i) - C(j)| <= 1
因此,您需要放宽约束。老实说,虽然我感觉到为什么4
已经到位(为了避免无限期地推迟一家公司的分销),我认为可以另外表达,认为分配的第一天和最后一天是特殊的(从那以后)在第一天,你通常会拿走前一家公司留下的东西,并在最后一天分发剩下的东西。
第3点确实强制了连续性。
在数学上:
对于任何有产品的公司A,有两天i和j,以便:
不可否认,问题变得微不足道了:)
答案 3 :(得分:0)
我认为您无法始终满足您的要求。
考虑4天,供应商A的6个项目和供应商B的6个项目。