算法分析习题集 Java版
目录
4.n元素幂集
5.插入排序
6.俄式乘法
7.AVL树
8.数学三角形
9.最长上升子序
10.投资分配
11.活动安排——贪心算法
12.一般背包问题——贪心算法
4.n元素幂集
Java代码:
思路:减一法 ——>利用递推式:p(n) = p(n-1) + IPN (IPN为前项和后项的一种关系)
import java.util.ArrayList;
public class PowerSet {
public static void main(String[] args) {
String[] a = { "1", "2","3", "4" };
ArrayList<String> pn = getSet(a); //
System.out.println("Set size is = " + pn.size());
for (int i = 0; i < a.length; i++) {
String string = a[i];
}
System.out.println(pn.toString());
}
public static ArrayList<String> getSet(String[] a) {
ArrayList<String> pn = new ArrayList<String>(); // creat a list to save set
pn.add("");
for (int i = 0; i < a.length; i++) {
pn.addAll(IPN(pn, a[i])); // 递推式:p(n) = p(n-1) + IPN p(0) = {"","1"}; p(1) = p{"","1","2","1,2"}...
// System.out.println("pn.addAll = " + pn.toString());
// System.out.println("--------------------");
}
return pn;
}
public static ArrayList<String> IPN(ArrayList<String> pn, String i) {
ArrayList<String> tmp = new ArrayList<String>();
for (int k = 0; k < pn.size(); k++) {
// System.out.println("pn.get[k] = " + pn.get(k));
tmp.add(pn.get(k) + i); // 临时list存储元素
// System.out.printf("tmp.get(%d) = %s\n", k, tmp.get(k));
}
return tmp;
}
}
运行结果:
Set size is = 16
[, 1, 2, 12, 3, 13, 23, 123, 4, 14, 24, 124, 34, 134, 234, 1234]
C代码
思路:递归法——>树的先序遍历
//递归树的叶子节点 int P(char *str, int n,int index){ static char tmp[10]; int case1 = 0, case2 = 0; if(n==-1){ //递归结束条件,输出叶子节点 tmp[index] = '\0'; //最后的变换为0,起是否选择n作用 printf("%s\t", tmp); return 1; //数量+1 } else{ tmp[index] = str[strlen(str)-1 - n]; //默认选取index,反转一下正序,也可以只是n case1 = P(str, n - 1, index + 1); //继续选,所以index+1 case2 = P(str, n - 1, index); //不选,由于默认选取了,需要覆盖,所以不加1 } //printf("\n"); return case1 + case2; //数量总和 } int main() { char tmp[10]; int cnt; printf("输入字符串: "); scanf("%s", tmp); cnt = P(tmp, strlen(tmp)-1, 0); printf("共有%d情况", cnt); return 0; }
运行结果:
输入字符串: abc
abc ab ac a bc b c 共有8情况
5.插入排序
代码:
import java.util.Arrays; /* * 应用插入排序对序列2,6,1,4,5,3,2进行排序 */ public class InsertSort { public static void main(String[] args) { int[] a = { 2, 6, 1, 4, 5, 3, 2 }; Insertsort(a); System.out.println(Arrays.toString(a)); } public static void Insertsort(int[] a) { int i, j; for (i = 1; i < a.length; i++) { int cur = a[i]; // 待比较值 for (j = i - 1; j >= 0 && a[j] > cur; j--) { a[j + 1] = a[j]; } a[j + 1] = cur; } } }
运行结果:
[1, 2, 2, 3, 4, 5, 6]
6.俄式乘法
代码:
import java.util.Scanner; public class RussianMultiplication { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("请输入两个数字(回车符间隔)"); int n = sc.nextInt(); int m = sc.nextInt(); sc.close(); int res = Rmult(n, m); System.out.printf("%d * %d == %d", n, m, res); } public static int Rmult(int n, int m) { int sum = 0; while (n != 0) { if (n % 2 != 0) { n--; // 奇数情况 sum += m; } else { n >>= 1; m <<= 1; } } return sum; } }
运行结果:
请输入两个数字(回车符间隔)
50
65
50 * 65 == 3250
7.AVL树
public class AVLTree<Key extends Comparable<? super Key>, Value> { private class Node { Key key;// 键,相当于词典里的单词 Value value;// 值,相当于词典里的单词解释 int height;// 结点的高度 Node left; Node right; public Node(Key key, Value value) { this.key = key; this.value = value; this.left = null; this.right = null; int height = 1; } } private Node root; // 根节点 public AVLTree() { root = null; } // 获取节点高度 private int height(Node node) { if (node != null) { return node.height; } return 0; } // 获取根高度 public int height() { return height(root); } private int max(int a, int b) { return a > b ? a : b; // 获取较大值 } // 替换节点? private void replaceNode(Node src, Node tar) { tar.key = src.key; tar.value = src.value; } // 遍历---------------------------------------------------- // 先序遍历 private void preOrder(Node node) { if (node != null) { System.out.print(node.key + " "); preOrder(node.left); preOrder(node.right); } } public void preOrder() { preOrder(root); } // 中序遍历 private void inOrder(Node node) { if (node != null) { inOrder(node.left); System.out.print(node.key + " "); inOrder(node.right); } } public void InOrder() { inOrder(root); } // 后序遍历 private void postOrder(Node node) { if (node != null) { postOrder(node.left); postOrder(node.right); System.out.print(node.key + " "); } } public void postOrder() { postOrder(root); } // ------------------------------------------------------- // 查找key位置 private Node search(Node node, Key key) { if (node == null) { return null; } else if (key.compareTo(node.key) == 0) { return node; } else if (key.compareTo(node.key) < 0) { return search(node.left, key); // 左子树 } else { // key.compareTo(node.key) > 0 return search(node.right, key); // 右子树 } } public Node Search(Key key) { return search(root, key); } // 返回最小左节点 private Node minNode(Node node) { if (node == null) { return null; } else if (node.left == null) { return node; } else { return minNode(node.left); } } public Node minNode() { return minNode(root); } // 返回最大右节点 private Node maxNode(Node node) { if (node == null) { return null; } else if (node.right == null) { return node; } else { return maxNode(node.right); } } public Node maxNode() { return maxNode(root); } // 旋转---------------------------------------------------- public Node leftLeftRotation(Node k1) { /* * LL单旋转 --- 右旋转 */ Node k2 = k1.left; // 失衡点左子树是k2 k1.left = k2.right; // k2的右子树变为 失衡点k1的左子树 k2.right = k1; // k2的右子树变为k1 // 重新计算各子树的高度 k1.height = max(height(k1.left), height(k1.right)) + 1; k2.height = max(height(k2.left), height(k2.right)) + 1; return k2; // 返回平衡后的点k2 } public Node rightRightRotation(Node k1) { /* * RR单旋转 --- 左旋转 */ Node k2 = k1.right; // 失衡点左子树是k2 k1.right = k2.left; // k2的右子树变为 失衡点k1的左子树 k2.left = k1; // k2的右子树变为k1 // 重新计算各子树的高度 k1.height = max(height(k1.left), height(k1.right)) + 1; k2.height = max(height(k2.left), height(k2.right)) + 1; return k2; // 返回平衡后的点k2 } public Node leftRightRotation(Node k1) { /* * LR双旋转 */ k1.left = rightRightRotation(k1.left); // 左旋 return leftLeftRotation(k1); // 右旋 } public Node rightLeftRotation(Node k1) { /* * RL双旋转 */ k1.right = leftLeftRotation(k1.right); // 左旋 return rightRightRotation(k1); // 右旋 } // ----------------------------------------------------- // 插入并调整为平衡树 private Node insert(Node node, Key key, Value value) { if (node == null) return new Node(key, value); if (key.compareTo(node.key) == 0) {// key相同,更新节点 node.value = value; } else if (key.compareTo(node.key) < 0) { node.left = insert(node.left, key, value); // 递归找左子树 if (height(node.left) - height(node.right) == 2) { // 不平衡,需要进行调整 if (key.compareTo(node.left.key) < 0) { node = leftLeftRotation(node); // 比节点的左key小,LL情况 } else { node = leftRightRotation(node); // 比节点的右key小,RR情况 } } } else { node.right = insert(node.right, key, value); // 递归找右子树 if (height(node.right) - height(node.left) == 2) { if (key.compareTo(node.right.key) > 0) { node = rightRightRotation(node); // 比节点的右key大,RR情况 } else { node = rightLeftRotation(node); } } } node.height = max(height(node.right), height(node.left)) + 1; // 调整高度 return node; // 返回根节点 } public void insert(Key key, Value value) { this.root = insert(this.root, key, value); } // 删除 public Node remove(Node node, Node target) { /** * @param node 当前子树根节点 * @parma target 要删除的节点 return 删除后的新的子树根 */ if (node == null || target == null) return node; // 空情况 if (target.key.compareTo(node.key) < 0) { node.left = remove(node.left, target); // 左子树继续找 if (Math.abs(height(node.right) - height(node.left)) == 2) { // 失衡 if (height(node.right.left) < height(node.right.right)) { node = rightRightRotation(node); // 左旋 } else { node = leftLeftRotation(node); // 右旋 } } } else if (target.key.compareTo(node.key) > 0) { node.right = remove(node.right, target); // 右子树继续找 if (Math.abs(height(node.left) - height(node.right)) == 2) {// 失衡 if (height(node.left.right) < height(node.left.left)) { node = leftLeftRotation(node); // 右旋 } else { node = rightRightRotation(node); // 左旋 } } } else {// node.key == target.key if (node.left == null) { return node.right; // 左子树null,那么删除后右子树变为根 } else if (node.right == null) { return node.left; // 右子树null,那么删除后左子树变为根 } else { // 左右子树 均存在 if (height(node.left) > height(node.right)) { // 左子树 深于 右子树 Node predecessor = maxNode(node.left); replaceNode(predecessor, node); // 替换 node.left = remove(node.left, predecessor); } else {// 如果右子树比左子树深(一样深的话无所谓了) Node successor = minNode(node.right);// 找node的后继结点successor replaceNode(successor, node);// successor替换node node.right = remove(node.right, successor);// 再把原来的successor删掉 } } } return node; } public void remove(Key key) { Node z; if ((z = search(root, key)) != null) // 找到key位置 root = remove(root, z); } // 销毁AVL树---------------------------------------------- private void destroy(Node node) { if (node == null) return; if (node.left != null) destroy(node.left); // 摧毁左子树 if (node.right != null) destroy(node.right); // 摧毁右子树 node = null; } public void destroy() { destroy(root); System.out.println("销毁完毕"); } // --------------------------------------------------------- // 递归输出AVL树的信息------------------------------------------------ private void print(Node tree, Key key, String pos) { if (tree != null) { if (pos.equals("")) // tree是根节点 System.out.printf("%2d is root\n", tree.key); else System.out.printf("%2d is %2d's %6s child\n", tree.key, key, pos); print(tree.left, tree.key, "left"); // 左子树 print(tree.right, tree.key, "right"); // 右子树 } } public void print() { if (root != null) print(root, root.key, ""); } // ----------------------------------------------------------- private static int arr[] = { 3, 2, 1, 4, 5, 6, 7, 16, 15, }; public static void main(String[] args) { int i; AVLTree<Integer, Integer> tree = new AVLTree<>(); System.out.printf("*******依次添加: "); for (i = 0; i < arr.length; i++) { System.out.printf("%d ", arr[i]); tree.insert(arr[i], arr[i]); } System.out.println("\n前序遍历"); tree.preOrder(); System.out.println("\n中序遍历"); tree.InOrder(); System.out.println("\n后序遍历"); tree.postOrder(); System.out.println("\n高度 : " + tree.height()); System.out.println("最小值: " + tree.minNode().key); System.out.println("最大值: " + tree.maxNode().key); System.out.println("\n树的详细信息:"); tree.print(); i = 5; System.out.printf("\n删除节点 : %d", i); tree.remove(i); System.out.println("树的高度 : " + tree.height()); System.out.print("中序遍历: "); tree.InOrder(); System.out.println("\n树的详细信息: "); tree.print(); tree.destroy(); // 销毁树 } }
运行结果:
*******依次添加: 3 2 1 4 5 6 7 16 15
前序遍历
5 3 2 1 4 7 6 16 15
中序遍历
1 2 3 4 5 6 7 15 16
后序遍历
1 2 4 3 6 15 16 7 5
高度 : 3
最小值: 1
最大值: 16
树的详细信息:
5 is root
3 is 5's left child
2 is 3's left child
1 is 2's left child
4 is 3's right child
7 is 5's right child
6 is 7's left child
16 is 7's right child
15 is 16's left child
删除节点 : 5树的高度 : 3
中序遍历: 1 2 3 4 6 7 15 16
树的详细信息:
6 is root
3 is 6's left child
2 is 3's left child
1 is 2's left child
4 is 3's right child
7 is 6's right child
16 is 7's right child
15 is 16's left child
销毁完毕
8.数学三角形
题目:
代码:
1 public class MathematicalTriangle { 2 3 public static void main(String[] args) { 4 int[][] a = { { 1 }, { 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 , 10} }; 5 6 for (int i = 0; i < a.length; i++) { 7 for (int j = 0; j < a[i].length; j++) { 8 System.out.printf("%4d", a[i][j]); 9 } 10 System.out.println(); 11 } 12 System.out.println(); 13 int res = minimunTotal(a); 14 15 System.out.println("min path : " + res); 16 } 17 18 public static int minimunTotal(int[][] triangle) { 19 int row = triangle.length; // 行 20 int column = triangle[row - 1].length; // 列 21 22 int[][] dp = new int[row][column]; // 辅助矩阵 23 dp[0][0] = triangle[0][0]; 24 25 for (int i = 1; i < row; i++) { 26 // 每一行元素进行推导 27 for (int j = 0; j <= i; j++) { 28 if (j == 0) { 29 // 最左端处理 30 dp[i][j] = dp[i - 1][j] + triangle[i][j]; 31 } else if (j == i) { 32 // 最右端处理 没有上面 33 dp[i][j] = dp[i - 1][j - 1] + triangle[i][j]; 34 } else { 35 dp[i][j] = Math.min(dp[i - 1][j - 1], dp[i - 1][j]) + triangle[i][j]; 36 } 37 } 38 } 39 40 int res = Integer.MAX_VALUE; 41 for (int i = 0; i < column; i++) { 42 res = Math.min(res, dp[row - 1][i]); 43 } 44 45 for (int i = 0; i < dp.length; i++) { 46 for (int j = 0; j < dp[i].length; j++) { 47 System.out.printf("%4d", dp[i][j]); 48 } 49 System.out.println(); 50 } 51 return res; 52 } 53 }
运行结果:
9.最长上升子序
题目:
代码:
1 import java.util.Arrays; 2 3 public class LongestSubsequence { 4 public static void main(String[] args) { 5 int[] nums = { 5, 8, 9, 2, 3, 1, 7, 4, 6 }; 6 int n = Solution.lengthOfLIS(nums); 7 System.out.println("\n最长子序长度:" + n); 8 } 9 } 10 11 class Solution { 12 13 public static int lengthOfLIS(int[] nums) { 14 int len = nums.length, max = 0; 15 int[] dp = new int[len]; 16 Arrays.fill(dp, 1); // 初始化为1 17 18 for (int i = 1; i < len; i++) { 19 for (int j = 0; j < i; j++) { 20 if (nums[j] < nums[i] && dp[i] < dp[j] + 1) { // 前面有比我小的吗? 21 dp[i] = dp[j] + 1; // 有的,那就取当前比较大的状态 22 } 23 } 24 if (max < dp[i]) { 25 max = dp[i]; 26 } 27 } 28 29 int[] arr = new int[max]; 30 System.out.print("最长子序:"); 31 for (int i = nums.length - 1; i >= 0; i--) { 32 if (dp[i] == max) { 33 arr[max - 1] = nums[i]; 34 max--; 35 } 36 } 37 for (int i : arr) { 38 System.out.print(i + " "); 39 } 40 41 int res = 0; 42 for (int i = 0; i < len; i++) { 43 res = Math.max(res, dp[i]); 44 } 45 return res; 46 } 47 }
运行结果:
最长子序:2 3 4 6
最长子序长度:4
10.投资分配
题目:
代码:
1 public class ResourceAllocation { 2 3 public static void main(String[] args) { 4 int[][] f = { { 0, 0, 0, 0, 0 }, // 没有第0个项目 5 { 0, 15, 28, 40, 51 }, { 0, 13, 29, 43, 55 }, { 0, 11, 30, 45, 58 }, }; 6 7 System.out.println("最大利润:" + SolutionInvest.investMax(f)); 8 } 9 } 10 11 class SolutionInvest { 12 static int M = 4 + 1; // 投资总数+1,4万元, 因为多了一列0向量 13 static int N = 3 + 1; // 项目数+1,3项目, 因为多了一行0向量 14 15 public static int investMax(int[][] f) { 16 /* 17 * 返回最大利润 18 * 19 * @param f:投资矩阵 20 */ 21 22 int[][] Fsum = new int[N][M]; // 前N个项目共投资M万元的最大收益 23 int[][] aItem = new int[N][M]; // 共投资M万元时第N个项目的投资金额,用于追溯路径 24 25 // 初始化表格的情况,即边界情况,具体情况看可表格 26 for (int i = 0; i < M - 1; i++) { 27 Fsum[1][i] = f[1][i]; 28 aItem[1][i] = i; 29 } 30 31 // 第 k 个项目的投资 32 for (int k = 2; k <= N - 1; k++) { 33 // 第一行一列是0,第一行即只投资一个项目的情况已经初始化,故从2开始 34 for (int m = 1; m <= M - 1; m++) { // M是投资数+1,所以此处循环到M-1 35 // 前 K 个项目共分配 m 万元,计算出当投资m万元时候的最好方案 36 int max = -1, temp = 0; // 初始化利润为-1 37 for (int a = 0; a <= m; a++) { 38 // 第 k 个项目分配 a 万元, 计算对比当投资额为m万元时候,第K个项目的最好投资数 39 if (f[k][a] + Fsum[k - 1][m - a] > max) { 40 // fk(x) = d 表示:x 万元投给第 k 个项目的效益为 d. 41 // 对比 f2(1)+F1(0), f2(0)+F1(1) 得出好的投资方案 42 max = f[k][a] + Fsum[k - 1][m - a]; 43 temp = a; // 记录总投资为m万元时第k个项目的投资金额 44 } 45 } 46 Fsum[k][m] = max; // 前K个项目共投资m万元时候的最大收益 47 aItem[k][m] = temp; // 记录投资m万元时候第k个项目的投资金额 48 } 49 } 50 printArray(Fsum); 51 printArray(aItem); 52 printInfo(aItem); // 输出投资信息 53 return Fsum[N - 1][M - 1]; 54 } 55 56 private static void printInfo(int[][] aItem) { 57 int index = M - 1; 58 for (int k = N - 1; k > 0; k--) { 59 System.out.println("第" + k + "个项目,投资" + aItem[k][index] + "万元"); 60 index -= aItem[k][index]; 61 } 62 } 63 64 private static void printArray(int[][] a) { 65 for (int i = 0; i < a.length; i++) { 66 for (int j = 0; j < a[i].length; j++) { 67 System.out.printf("%4d", a[i][j]); 68 } 69 System.out.println(); 70 } 71 System.out.println(); 72 } 73 }
运行结果:
0 0 0 0 0
0 15 28 40 0
0 15 29 44 58
0 15 30 45 60
0 0 0 0 0
0 1 2 3 0
0 0 2 2 3
0 0 2 2 3
第3个项目,投资3万元
第2个项目,投资0万元
第1个项目,投资1万元
最大利润:60
代码(C语言版):
1 #include<iostream> 2 #define N 4//项目数+1 多了一行0矩阵 3 #define M 5//投资总额+1 多了一列0矩阵 4 5 using namespace std; 6 7 //aItem[3][2]表示共投资2万元第3个项目的投资金额,用于追溯路径 8 double aItem[N][M] = {0}; 9 //Fsum[3][2]表示前3个项目共投资2万元的最大收益 10 double Fsum[N][M] = { 0 }; 11 12 double investMax(double f[N][M]){ 13 // 前一个项目的情况 14 for (int i = 0; i <= M - 1;i++){ 15 Fsum[1][i] = f[1][i]; 16 aItem[1][i] = i; 17 } 18 // 第 k 个项目 19 for (int k = 2; k <= N - 1;k++){ 20 // 前 k 个项目 共 分配 m 万元 21 for (int m = 1; m <= M - 1; m++){ 22 double max = -1, temp = 0; 23 // 第 k 个项目分配 a 万元 24 for (int a = 0; a <= m; a++){ 25 if(f[k][a] + Fsum[k-1][m-a] > max){ 26 max = f[k][a] + Fsum[k - 1][m - a]; 27 temp = a; 28 } 29 } 30 Fsum[k][m] = max; // 前 k 个项目共投资 m 万元的最大收益 31 aItem[k][m] = temp; // 投资 m 万元第 k 个项目的投资金额 32 } 33 } 34 return Fsum[N - 1][M - 1]; 35 } 36 37 void printInfo(){ 38 int index = M - 1; 39 for (int k = N - 1; k > 0;k--){ 40 cout << "第" << k << "个项目,投资" << aItem[k][index] << "万元"<<endl; 41 index -= aItem[k][index]; // 剩余钱数 42 } 43 } 44 45 int main() { 46 47 double f[N][M] = {//f[1][2]表示投第1个项目2万元所产生的效益 48 {0, 0, 0, 0, 0},//没有第0个项目 49 {0,15,28,40,51}, 50 {0, 13, 29,43,55}, 51 {0, 11,30,45,58}, 52 }; 53 cout << M-1 <<"万元投资"<<N-1<<"项目最大收益为:" << investMax(f) << endl; 54 printInfo(); 55 56 printf("\n"); 57 for (int i = 0; i < N;i++){ 58 for (int j = 0; j < M;j++) 59 printf("%g \t", aItem[i][j]); 60 printf("\n"); 61 } 62 63 printf("\n"); 64 for (int i = 0; i < N;i++){ 65 for (int j = 0; j < M;j++) 66 printf("%g \t", Fsum[i][j]); 67 printf("\n"); 68 } 69 return 0; 70 }
运行结果:
4万元投资3项目最大收益为:60
第3个项目,投资3万元
第2个项目,投资0万元
第1个项目,投资1万元
0 0 0 0 0
0 1 2 3 4
0 0 2 2 3
0 0 2 2 3
0 0 0 0 0
0 15 28 40 51
0 15 29 44 58
0 15 30 45 60
11.活动安排——贪心算法
1 public class ActivityArrangement { 2 public static void main(String[] args) { 3 int[] s = { 0, 1, 3, 0, 5, 3, 5, 6, 8, 8, 2, 12 }; 4 int[] f = { 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }; 5 int n = 11; 6 boolean[] a = new boolean[12]; 7 int count = Greedy.ActiveManage(s, f, a, n); 8 System.out.println("可安排的活动总数:" + count); 9 System.out.print("选择活动如下:"); 10 for (int i = 0; i < a.length; i++) { 11 if (a[i] == true) { 12 System.out.print(i + " "); 13 } 14 } 15 } 16 } 17 18 class Greedy { 19 public static int ActiveManage(int[] s, int[] f, boolean a[], int n) { 20 /** 21 * 贪心策略:取当前活动集合中结束时间最早的相容活动,这样可以为未安排的活动留下心网能多的时间, 22 * 也就是说,这种贪心选择的目的是使剩余时间段极大化,以便安排尽可能多的相容活动。 23 * 24 * @param s : 活动起始时间 25 * @param f: 活动结束时间 26 * @param a: 是否选择活动 27 * @param n : 活动总数 28 * @return count: 安排的活动数 29 */ 30 a[1] = true; // 默认选择第一个活动 31 int j = 1, count = 1; // count 记录选取到的活动总数 32 for (int i = 2; i <= n; i++) { // 候选集合C 33 if (s[i] >= f[j]) { // 选择函数(贪心策略) 34 a[i] = true; // 解集合S 35 j = i; 36 count++; 37 } else { 38 a[i] = false; 39 } 40 } 41 return count; 42 } 43 }
运行结果:
可安排的活动总数:4
选择活动如下:1 4 8 11
12.一般背包问题——贪心算法
1 public class GeneralBackpack { 2 public static void main(String[] args) { 3 float[] w = { 0, 10, 30, 20 }; 4 float[] v = { 0, 50, 120, 60 }; 5 float[] x = new float[4]; 6 float C = 50; 7 int n = 4; 8 float total = bag.Knapsack(w, v, x, C, n); 9 System.out.println("总价值:" + total); 10 for (int i = 1; i < x.length; i++) { 11 System.out.printf("第%d个物品数量为:%f,价值为%f\n", i, x[i], x[i] * v[i]); 12 } 13 } 14 } 15 16 class bag { 17 public static float Knapsack(float[] w, float[] v, float[] x, float C, int n) { 18 /** 19 * n个物品已经按照V/W 由大到小 贪心策略:考虑价值增长和容量消耗二者的综合效果的方法,即每次选择价值与重量比u:/w 20 * 21 * @param w: 重量 22 * @param v: 价值 23 * @param x: 解 24 * @param C: 背包重量 25 * @param n: 物品数量 26 * @return total 总价值 27 */ 28 for (int i = 0; i < n; i++) { 29 x[i] = 0; // 初始化解向量 30 } 31 int i = 1; // 由于从1开始 所以w和v前面都要加0 32 float total = 0; // 总重量 33 while (w[i] < C) { // 可行函数feasible / 解决函数solution 34 x[i] = 1; 35 total = total + v[i]; // 解集合 —— 总价值 36 C = C - w[i]; // 剩余背包重量 37 i++; // 下一个物品 38 } 39 x[i] = C / w[i]; // 使用完剩余的一点空间 40 total = total + v[i] * x[i]; 41 return total; 42 } 43 }
运行结果:
总价值:200.0
第1个物品数量为:1.000000,价值为50.000000
第2个物品数量为:1.000000,价值为120.000000
第3个物品数量为:0.500000,价值为30.000000