From d52ac8e40c5b875b8844c45e217d2b7fcf3dc476 Mon Sep 17 00:00:00 2001 From: fujie <405295521@qq.com> Date: Sun, 20 Aug 2017 21:35:10 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=83=8C=E5=8C=85=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E8=A7=A3=E5=86=B3=E5=87=BD=E6=95=B0=E5=92=8C=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E7=94=A8=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../function/list/DpKnapsackFunction.java | 203 ++++++++++++++++ .../src/main/resources/collection.beans.xml | 217 +++++++++--------- .../src/test/resources/example/DPknapsack.ts | 74 ++++++ 3 files changed, 387 insertions(+), 107 deletions(-) create mode 100644 org.tinygroup.tinyscript.collection/src/main/java/org/tinygroup/tinyscript/collection/function/list/DpKnapsackFunction.java create mode 100644 org.tinygroup.tinyscript/src/test/resources/example/DPknapsack.ts diff --git a/org.tinygroup.tinyscript.collection/src/main/java/org/tinygroup/tinyscript/collection/function/list/DpKnapsackFunction.java b/org.tinygroup.tinyscript.collection/src/main/java/org/tinygroup/tinyscript/collection/function/list/DpKnapsackFunction.java new file mode 100644 index 0000000..c0cb406 --- /dev/null +++ b/org.tinygroup.tinyscript.collection/src/main/java/org/tinygroup/tinyscript/collection/function/list/DpKnapsackFunction.java @@ -0,0 +1,203 @@ +package org.tinygroup.tinyscript.collection.function.list; + +import java.lang.reflect.Array; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.tinygroup.tinyscript.ScriptContext; +import org.tinygroup.tinyscript.ScriptException; +import org.tinygroup.tinyscript.ScriptSegment; +import org.tinygroup.tinyscript.function.AbstractScriptFunction; +import org.tinygroup.tinyscript.interpret.LambdaFunction; +import org.tinygroup.tinyscript.interpret.ScriptResult; + +public class DpKnapsackFunction extends AbstractScriptFunction { + + private Integer[] items;// 存放每种物品的数量 + + @Override + public String getNames() { + // TODO Auto-generated method stub + return "DPknapsack"; + } + + @Override + public String getBindingTypes() { + return "java.util.List"; + } + + @Override + public Object execute(ScriptSegment segment, ScriptContext context, Object... parameters) throws ScriptException { + // TODO Auto-generated method stub + if (parameters == null || parameters.length <= 3) { + throw new ScriptException("sort函数的参数 错误!"); + } + List list = (List) parameters[0]; + int size = (Integer) parameters[1]; + Map lastresult = new HashMap(); + List result = null; + + if (checkParameters(parameters, 4)) {// 无限背包 + try { + LambdaFunction lambdaFunction = (LambdaFunction) parameters[3]; + Object v = lambdaFunction.execute(context, null).getResult(); + int[] count = new int[list.size() + 1]; + int[] w = (int[]) ConvertToArray(parameters[2], int.class); + for (int i = 1; i < count.length; i++) { + count[i] = size / w[i]; + } + result = DpKnapsackResult(w, (double[]) ConvertToArray(v, double.class), size, count); + + } catch (Exception e) { + throw new ScriptException("sort函数执行发生异常:", e); + } + } else if (checkParameters(parameters, 5)) {// 混合背包和多重背包 + try { + LambdaFunction lambdaFunction = (LambdaFunction) parameters[4]; + Object v = lambdaFunction.execute(context, null).getResult(); + int[] count = (int[]) ConvertToArray(parameters[3], int.class); + int[] w = (int[]) ConvertToArray(parameters[2], int.class); + for (int i = 1; i < count.length; i++) { + if (count[i] == -1) + count[i] = size / w[i]; + } + result = DpKnapsackResult(w, (double[]) ConvertToArray(v, double.class), size, count); + } catch (Exception e) { + throw new ScriptException("sort函数执行发生异常:", e); + } + } else if (checkParameters(parameters, 6)) {// 用户定义规则(目前是主件和附件) + try { + int[] rule = (int[]) ConvertToArray(parameters[4], int.class);// 主件和附件规则 + LambdaFunction lambdaFunction = (LambdaFunction) parameters[5]; + Object v = lambdaFunction.execute(context, null).getResult(); + result = DpKnapsackResult((int[]) ConvertToArray(parameters[2], int.class), + (double[]) ConvertToArray(v, double.class), size, + (int[]) ConvertToArray(parameters[3], int.class), rule); + } catch (Exception e) { + throw new ScriptException("sort函数执行发生异常:", e); + } + } + lastresult.put("result", result.get(0)); + for (int i = 1; i < result.size(); i++) { + lastresult.put(list.get(i - 1), result.get(i)); + } + return lastresult; + } + + private List DpKnapsackResult(int[] w, double[] v, int bagSize, int[] count, Object... rules) { + double result[][] = new double[w.length][bagSize + 1]; + // 计算最优解 + DpKnapsackResult(result, w.length - 1, bagSize, w, count, v, rules); + // 根据最优解查找最优方案 + items = new Integer[w.length]; + FindResult(w.length - 1, bagSize, result, w, v, count); + + List list = new ArrayList(); + Collections.addAll(list, items); + list.set(0, result[w.length - 1][bagSize]); + return list; + } + + /** + * 解决背包问题 + * @param f 最优值二维表 + * @param N 物品件数 + * @param V 最大容量 + * @param w 重量 + * @param count 物品限制件数 + * @param value 物品价值 + * @param rules 自定义规则(主件和附件) + */ + private void DpKnapsackResult(double f[][], int N, int V, int[] w, int[] count, double value[], + Object... rules) { + int nCount = 0; + for (int i = 0; i <= N; i++) { + f[i][0] = 0; + } + for (int v = 0; v <= V; v++) { + f[0][v] = 0; + } + for (int i = 1; i <= N; i++) { + for (int v = w[i]; v <= V; v++) { + f[i][v] = 0; + nCount = Math.min(count[i], v / w[i]); + for (int k = 0; k <= nCount; k++) { + if (rules != null && rules.length > 0) { + int[] rule = (int[]) rules[0]; + if (rule[i] == 0) {//考虑到主件和附件的情况 + if (w[i] <= v) { + f[i][v] = Math.max(f[i][v], f[i - 1][v - k * w[i]] + k * value[i]); + } + } else { + if (w[i] + w[rule[i]] <= v) { + f[i][v] = Math.max(f[i][v], f[i - 1][v - k * w[i]] + k * value[i]); + } + } + } else { + f[i][v] = Math.max(f[i][v], f[i - 1][v - k * w[i]] + k * value[i]); + } + } + } + } + } + + + /** + * 将数组或列表转为背包问题需要的数组 + * @param array 需要转化的对象有可能是数组也有可能是list + * @param clazz 需要转化的数组类型 + * @return + * @throws ScriptException + */ + private Object ConvertToArray(Object array, Class clazz) throws ScriptException { + Object obj = null; + if (array instanceof List) { + obj = Array.newInstance(clazz, ((List) array).size() + 1); + for (int i = 1; i < Array.getLength(obj); i++) { + if (clazz == int.class || clazz == Integer.class) { + Array.set(obj, i, Integer.parseInt(((List) array).get(i - 1) + "")); + } else { + Array.set(obj, i, Double.parseDouble(((List) array).get(i - 1) + "")); + } + } + } else if (array.getClass().isArray()) { + obj = Array.newInstance(clazz, Array.getLength(array) + 1); + System.arraycopy(array, 0, obj, 1, Array.getLength(array)); + } else { + throw new ScriptException("转换数组发生异常"); + } + return obj; + } + + /** + * @param i + * @param j 供递归调用的下标 + * @param f 存贮最佳结果的二维表 + * @param w 重量 + * @param v 价值 + * @param count 限制数量 + */ + private void FindResult(int i, int j, double[][] f, int[] w, double[] v, int count[]) { + if (i > 0) { + if (f[i][j] == f[i - 1][j]) { + items[i] = 0;// 全局变量,标记未被选中 + FindResult(i - 1, j, f, w, v, count); + } else if (j - w[i] >= 0) { + int min = Math.min(j / w[i], count[i]); + int temp = 0; + for (int k = 1; k <= min; k++) { + if (f[i - 1][j - k * w[i]] == f[i][j] - k * v[i]) { + temp = k; + break; + } + } + items[i] = temp;// 标记已被选中 + FindResult(i - 1, j - temp * w[i], f, w, v, count);// 回到装包之前的位置 + } + } + } + +} diff --git a/org.tinygroup.tinyscript.collection/src/main/resources/collection.beans.xml b/org.tinygroup.tinyscript.collection/src/main/resources/collection.beans.xml index b64c34b..f49e035 100644 --- a/org.tinygroup.tinyscript.collection/src/main/resources/collection.beans.xml +++ b/org.tinygroup.tinyscript.collection/src/main/resources/collection.beans.xml @@ -1,110 +1,113 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + xmlns="http://www.springframework.org/schema/beans" + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.tinygroup.tinyscript/src/test/resources/example/DPknapsack.ts b/org.tinygroup.tinyscript/src/test/resources/example/DPknapsack.ts new file mode 100644 index 0000000..3f9e28b --- /dev/null +++ b/org.tinygroup.tinyscript/src/test/resources/example/DPknapsack.ts @@ -0,0 +1,74 @@ +//参数说明:list.DPknapsack(容量,重量,[每件物品的件数],价值,[规则]) + +//01背包 +w = [2,2,6,5,4]; +count = [1,1,1,1,1]; +size = 10; +list = ["a","b","c","d","e"]; +result = list.DPknapsack(size,w,count,()->{ + return [6,3,5,4,6]; +}); +println("01背包问题:\n"+result); + +//完全背包 +w = [2,2,6,5,4]; +size = 10; +list = ["a","b","c","d","e"]; +result = list.DPknapsack(size,w,()->{ + return [6,3,5,4,6]; +}); +println("完全背包问题:\n"+result); + +//多重背包 +w = [12,2,1,4,1]; +size = 15; +count = [1,7,12,3,1]; +list = ["a","b","c","d","e"]; +result = list.DPknapsack(size,w,count,()->{ + return [4,2,1,10,2]; +}); +println("多重背包问题:\n"+result); + +//混合背包 +w = [12,2,1,4,1]; +size = 15; +count = [1,7,12,3,-1];//-1表示该物品无件数限制 +list = ["a","b","c","d","e"]; +result = list.DPknapsack(size,w,count,()->{ + return [4,2,1,10,2]; +}); +println("混合背包问题:\n"+result); + +/*小王有一笔钱m(5000),在t(80)时间内,想做理财投资,有如下几只理财产品,请给出最佳方案*/ +w = [100,100,100,100,100];//基金的最小购买额度 +count = [10,20,20,10,5];//购买基金的份数 +list = ["鹏华国防","鹏华中证","国投瑞银","华商主题精选","金鹰智慧"];//基金的名字 +result = list.DPknapsack(5000,w,count,()->{ + lilv = [0.00045,0.00035,0.00055,0.00040,0.00030];//基金的利率 + value = []; + for(i = 0;i{ + v = [1600,2000,1500,1200,1000]; + return v; +}); +println("购物单问题:\n"+result); + + -- Gitee