diff --git a/algorithm/MST.md b/algorithm/MST.md new file mode 100644 index 0000000..1e8ece6 --- /dev/null +++ b/algorithm/MST.md @@ -0,0 +1,56 @@ +# 最小生成树 + +## 1. Prim算法 +### 1.1 算法描述 +TODO + +### 1.2 代码 + +``` C++ +int Prim(vector >&G, int start){ + /* + 用Prim算法求最小生成树的代价. + Prim算法: + 又称"加点法", 每次选择横跨最小生成树内外的边中代价最小的边对应的点, 加入到最小生成树中。 + 参数: + G: 连通图的邻接矩阵 + start: 起始结点编号 + + 时间复杂度O(v^2) + */ + int n = G.size(); // 顶点数 + int res = 0; + + vectorprocessd(n, 0); // 是否已经被处理(即是否已在生成树中) + processd[start] = 1; + + vectorlowCost(n, 0); // 记录每个结点到生成树结点集合的最短边长度 + for(int i = 0; i < n; i++) + if(i != start) lowCost[i] = G[start][i]; + + // 不断加入剩下的 n-1 个结点到生成树结点集合中 + for(int i = 1; i < n; i++){ // 循环 n-1 次 + int mincost = 0x7FFFFFFF, v = -1; + for(int j = 0; j < n; j++){ + if(!processd[j] && mincost >= lowCost[j]){ + mincost = lowCost[j]; + v = j; + } + } + if(v == -1){ + cout << "Error: 输入的图不是连通图!!!" << endl; + return -1; + } + // 将结点v加入到已处理集合中 + processd[v] = 1; res += mincost; + // 更新每个结点到生成树结点集合的最短边长度 + for(int j = 0; j < n; j++) + if(!processd[j] && G[v][j] < lowCost[j]) + lowCost[j] = G[v][j]; + } + return res; +} +``` + +## 2. Kruskal算法 +TODO \ No newline at end of file diff --git a/algorithm/README.md b/algorithm/README.md new file mode 100644 index 0000000..8c478c2 --- /dev/null +++ b/algorithm/README.md @@ -0,0 +1,9 @@ +# 经典算法总结 + +## 图 + +* [最小生成树](MST.md) + +## 动态规划 + +* [背包问题](pack_problem.md) \ No newline at end of file diff --git a/algorithm/pack_problem.md b/algorithm/pack_problem.md new file mode 100644 index 0000000..9cdd6a6 --- /dev/null +++ b/algorithm/pack_problem.md @@ -0,0 +1,56 @@ +# 背包问题 + +## 1 算法描述 + +背包问题系列总结见[我的博客](https://tangshusen.me/2019/11/24/knapsack-problem/)。 + +## 2 代码 + +``` C++ +/* +https://tangshusen.me/2019/11/24/knapsack-problem/ +01背包, 完全背包, 多重背包模板(二进制优化). +2020.01.04 by tangshusen. + +用法: + 对每个物品调用对应的函数即可, 例如多重背包: + for(int i = 0; i < N; i++) + multiple_pack_step(dp, w[i], v[i], num[i], W); + +参数: + dp : 空间优化后的一维dp数组, 即dp[i]表示最大承重为i的书包的结果 + w : 这个物品的重量 + v : 这个物品的价值 + n : 这个物品的个数 + max_w: 书包的最大承重 +*/ +void zero_one_pack_step(vector&dp, int w, int v, int max_w){ + for(int j = max_w; j >= w; j--) // 反向枚举!!! + dp[j] = max(dp[j], dp[j - w] + v); +} + +void complete_pack_step(vector&dp, int w, int v, int max_w){ + for(int j = w; j <= max_w; j++) // 正向枚举!!! + dp[j] = max(dp[j], dp[j - w] + v); + + // 法二: 转换成01背包, 二进制优化 + // int n = max_w / w, k = 1; + // while(n > 0){ + // zero_one_pack_step(dp, w*k, v*k, max_w); + // n -= k; + // k = k*2 > n ? n : k*2; + // } +} + +void multiple_pack_step(vector&dp, int w, int v, int n, int max_w){ + if(n >= max_w / w) complete_pack_step(dp, w, v, max_w); + else{ // 转换成01背包, 二进制优化 + int k = 1; + while(n > 0){ + zero_one_pack_step(dp, w*k, v*k, max_w); + n -= k; + k = k*2 > n ? n : k*2; + } + } +} +``` \ No newline at end of file