CSDN曾卫大牛的Java代码(https://blog.csdn.net/u014344668/article/details/109491754),正好有个需求用到(开有额度限制的发票,尽可能的张数最少),请求帮忙转为Delphi,谢谢。
需求:
1.目标数组 {10,6,5,3,10,2,1,1,6,1,1}
2.要求组合之和不能大于10,且组合最小
CSDN曾卫大牛的Java代码(https://blog.csdn.net/u014344668/article/details/109491754),正好有个需求用到(开有额度限制的发票,尽可能的张数最少),请求帮忙转为Delphi,谢谢。
需求:
1.目标数组 {10,6,5,3,10,2,1,1,6,1,1}
2.要求组合之和不能大于10,且组合最小
算法实现
/**
* @Description: 最优组合算法
* @Author zengwei
* @Date 2020-11-03-18:32
**/
public class TheBestCombineAlgorithm {
public static void main(String[] args){
int[] arr = {10,6,5,3,10,2,1,1,6,1,1};
int max = 10;
int[][] end = getArray(arr,max);
for (int[] ints : end) {
if (ints != null) {
System.out.println(Arrays.toString(ints));
}
}
}
private static int[][] getArray(int[] arr, int max) {
List<Integer> recordIndex = new ArrayList<>();//记录使用过的元素的索引位置
int[][] finalArray = new int[arr.length][];
//1.从左到右遍历所有元素
int arrIndex = 0;//记录二维数组的位置
for (int i=0;i<arr.length;i++){//每循环一次,位置往后移动一次
int currentElement = arr[i];
if(recordIndex.contains(i)){
continue;//如果当前位置被使用了,跳过本次循环,进入下次循环
}
//判断当前元素是否已经大于后者等于10
if(currentElement >= max){
finalArray[arrIndex] = new int[]{currentElement};
//同时将当前索引位置存入到list中
recordIndex.add(i);
}else{
List<Integer> element = new ArrayList<>();
element.add(currentElement);
while(currentElement <max){
//2.除了当前元素外,查找最小元素
int searchMinIndex = bubble(i,arr,recordIndex);
if(searchMinIndex == -1){
break;
}
currentElement += arr[searchMinIndex];
if(currentElement > max){
break;//因为如果相加大于10,说明不需要这个值了
}
//3.拼接到新的int数组中
element.add(arr[searchMinIndex]);
//4.将当前索引位置存入recordIndex中
recordIndex.add(searchMinIndex);
}
//JDK1.8特性 将List对象转为int[]数组
finalArray[arrIndex] = element.stream().mapToInt(j -> j).toArray();
}
arrIndex ++;
}
//4.存入到新的二维数组中
return finalArray;
}
/**
* 冒泡比较,查找最小元素位置
* @param i 查找开始位置
* @param arr 目标数组
* @param recordIndex 存储已经被使用的元素
* @return 返回最小元素索引位置
*/
private static int bubble(int i, int[] arr, List<Integer> recordIndex) {
int min = arr[i];//记录最小元素的值
int index = -1;//记录最小元素位置
for (;i<arr.length;i++){
if(recordIndex.contains(i)){
continue;
}
if(min > arr[i]){//每次都和最小值比较
min = arr[i];
index = i;
}
}
return index;
}
}
输出结果
[10]
[6, 1, 1, 1, 1]
[5, 2, 3]
[10]
[6]
郑重感谢:以下Delphi版算法来自Delphi盒子用户:devil10086 (testabc) 。感谢devil10086 (testabc)为Delphi社区做出的贡献。欢迎加入Delphi开发局QQ群:32422310 Delphi控件源码下载网站
unit Unit2;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm2 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Memo2: TMemo;
Button2: TButton;
Memo3: TMemo;
Button3: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
uses
System.Generics.Collections;
type
TArrayEx = array of array of Integer;
const
arrInput: TArray<Integer> = [10,6,5,3,10,2,1,1,6,1,1];
Max = 20;
/// <summary>
/// * 冒泡比较,查找最小元素位置
///* @param i 查找开始位置
///* @param arr 目标数组
///* @param recordIndex 存储已经被使用的元素
///* @return 返回最小元素索引位置
/// </summary>
function bubble(i: Integer; inArr: TArray<Integer>; recordIndex: TList<Integer>): Integer;
var
min, index, iTemp: Integer;
begin
min := inArr[i];//记录最小元素的值
index := -1;//记录最小元素位置
for iTemp := 0 to Pred(Length(inArr)) do
begin
if(recordIndex.contains(iTemp)) then
continue;
if(min > = inArr[iTemp]) then//每次都和最小值比较
begin
min := inArr[iTemp];
index := iTemp;
end;
end;
Result := index;
end;
function getArray(arr: TArray<Integer>; max: Integer): TArrayEx;
var
recordIndex, element: TList<Integer>;
finalArray: TArrayEx;
arrIndex: Integer; //记录二维数组的位置
i,j, currentElement, searchMinIndex: Integer;
begin
recordIndex := TList<Integer>.Create;
SetLength(finalArray,Length(arr), Length(arr));
//1.从左到右遍历所有元素
arrIndex := 0;
for i := 0 to Pred(Length(arr)) do
begin
currentElement := arr[i];
if recordIndex.Contains(i) then
Continue; //如果当前位置被使用了,跳过本次循环,进入下次循环
//判断当前元素是否已经大于后者等于10
if(currentElement >= max) then
begin
finalArray[arrIndex] := [currentElement];
//同时将当前索引位置存入到list中
recordIndex.add(i);
end
else
begin
element := TList<Integer>.Create;
element.add(currentElement);
while(currentElement < max) do
begin
//2.除了当前元素外,查找最小元素
searchMinIndex := bubble(i,arr,recordIndex);
if(searchMinIndex = -1) then
Break;
currentElement := currentElement + arr[searchMinIndex];
if(currentElement > max) then
Break; //因为如果相加大于10,说明不需要这个值了
//3.拼接到新的int数组中
element.add(arr[searchMinIndex]);
//4.将当前索引位置存入recordIndex中
recordIndex.add(searchMinIndex);
end;
//将List对象放入数组
for j := 0 to element.Count-1 do
finalArray[arrIndex, j] := element.Items[j];
end;
inc(arrIndex);
end;
Result := finalArray;
end;
procedure TForm2.Button1Click(Sender: TObject);
procedure p_test(AMax: integer ; mmo: TMemo);
var
outPut: TArrayEx;
i, j: Integer;
s: string;
begin
// output := getArray(arrInput,Max);
output := getArray(arrInput,AMax);
mmo.Lines.Clear;
for i:= Low(outPut) to High(outPut) do
begin
s := '';
for j := Low(outPut[i]) to High(outPut[i]) do
if outPut[i, j] > 0 then
s := s + ' ' + IntToStr(outPut[i, j]);
if s<>'' then
mmo.Lines.Add(s);
end;
end;
begin
if sender=Button1 then p_test(10,memo1)
else if sender=Button2 then p_test(15,memo2)
else if sender=Button3 then p_test(20,memo3)
end;
procedure TForm2.FormCreate(Sender: TObject);
begin
Button1Click(Button1);
Button1Click(Button2);
Button1Click(Button3);
end;
end.
窗体代码:
object Form2: TForm2
Left = 0
Top = 0
Caption = 'Form2'
ClientHeight = 236
ClientWidth = 686
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object Label1: TLabel
Left = 8
Top = 8
Width = 181
Height = 13
Caption = #30446#26631#25968#32452': [10,6,5,3,10,2,1,1,6,1,1]'
end
object Button1: TButton
Left = 8
Top = 33
Width = 220
Height = 25
Caption = #35201#27714#32452#21512#20043#21644#19981#33021#22823#20110'10'#65292#19988#32452#21512#26368#23567
TabOrder = 0
OnClick = Button1Click
end
object Memo1: TMemo
Left = 8
Top = 64
Width = 220
Height = 153
Lines.Strings = (
'Memo1')
TabOrder = 1
end
object Memo2: TMemo
Left = 234
Top = 64
Width = 220
Height = 153
Lines.Strings = (
'Memo1')
TabOrder = 2
end
object Button2: TButton
Left = 234
Top = 33
Width = 220
Height = 25
Caption = #35201#27714#32452#21512#20043#21644#19981#33021#22823#20110'15'#65292#19988#32452#21512#26368#23567
TabOrder = 3
OnClick = Button1Click
end
object Memo3: TMemo
Left = 458
Top = 64
Width = 220
Height = 153
Lines.Strings = (
'Memo1')
TabOrder = 4
end
object Button3: TButton
Left = 458
Top = 33
Width = 220
Height = 25
Caption = #35201#27714#32452#21512#20043#21644#19981#33021#22823#20110'20'#65292#19988#32452#21512#26368#23567
TabOrder = 5
OnClick = Button1Click
end
end
效果: