现有一列随机的正整数,算他有2^n个吧,然后两两结合生成一个二叉树,节点是上一级两个数的和,合成的cost是上一级两个数的乘积。
而整个树的cost由总cost最高的那个branch决定,求用什么方法排列这一列数使生成的树cost最低。

例如,1,2,3,4这四个数

二叉树

C=21+12=33

% 将一个树分成等长的左子树和右子树
bisect(List, Left, Right) :-
  append(Left, Right, List),
  length(Left, LeftLength),
  length(Right, RightLength),
  LeftLength = RightLength.

% 计算节点Cost = 左子树数字和 * 右子树数字和
element_cost(List, Cost) :-
  bisect(List, Left, Right),
  sum_list(Left, LeftSum),
  sum_list(Right, RightSum),
  Cost is (LeftSum * RightSum).

% 计算整树Cost = 节点Cost + Max(左子树Cost, 右子树Cost)
% (叶子节点的整树Cost = 0)
tree_cost([_], 0).
tree_cost(List, Cost) :-
  bisect(List, Left, Right),
  tree_cost(Left, LeftCost),
  tree_cost(Right, RightCost),
  max_list([LeftCost, RightCost], BiggerCost),
  element_cost(List, ElementCost),
  Cost is (ElementCost + BiggerCost).

% 所有可能的树和树Cost
all_cost(List, TargetList, Cost) :-
  permutation(List, TargetList),
  tree_cost(TargetList, Cost).

% 获得最小的树Cost
min_cost(List, Cost) :-
  findall(TargetCost, all_cost(List, _, TargetCost), CostList),
  min_list(CostList, Cost).

% 获得最小的树Cost和树列表
min_cost_with_list(List, MinList, Cost) :-
  findall([TargetList, TargetCost], all_cost(List, TargetList, TargetCost), AllList),
  maplist(last, AllList, CostList),
  min_list(CostList, Cost),
  member([MinList, Cost], AllList).