算法导论第十六章
16.1
16.1-1
int c[n+1][n+1]; int b[n+1][n+1]; for (int i = 0; i <= n; i++) { for (int j = 0; j <= n; j++) { c[i][j] = -1; b[i][j] = 0; } } void ACTIVITY_SELECTOR(int *s, int *f, int *c, int *b, int i, int j) { if (c[i][j] != -1) return; int flag = 0; for (int k = i+1; k < j; k++) { if (s[k] >= f[i] && e[k] <= s[j]) flag = 1; } if (!flag) { c[i][j] = 0; } for (int k = i+1; k < j; k++) { ACTIVITY_SELECTOR(s, f, c, i, k); ACTIVITY_SELECTOR(s, f, c, k, j); res = c[i][k] + c[k][j] + 1; if (res > c[i][j]) { b[i][j] = k; c[i][j] = res; } } return; }
将递归式改为迭代式可得,时间复杂度为\(\Theta(n^3)\)
而贪心策略的结果为\(\Theta(n)\)
16.1-2
struct Activity
{
int s;
int f;
bool operator < (const activity &other)
{
if (s < other.s) return true;
else return false;
}
}
vector<int> GREEDY_SELECTOR(vector<Activity> activity)
{
sort(activity.begin(), activity.end());
vector<int> res;
int k = activity.size()-1;
res.push_back(k);
for (int m = k-1; m >= 1; m--)
{
if (activity[m].f <= activity[k].s)
{
res.push_back(m);
k = m;
}
}
return res;
}
[/code]
证明:
命题:对于任意非空子问题\(S_k\), 令\(a_m\)是\(S_k\)中开始时间最晚的活动。则\(a_m\)在\(S_k\)的某个最大兼容活动子集中。
令\(A_k\)是\(S_k\)的一个最大兼容活动子集,且\(a_j\)是其中开始时间最晚的活动。若\(a_j = a_m\), 证毕。
否则,令\(A_{k'}\) = (\(A_k\) - {\(a_j\)})||{\(a_m\)}(\(a_m开始时间晚于a_j\))
由于\(A_k\)中活动不相交,所以\(A_{k'}\)中活动不相交。
又\(|A_k| = |A_{k'}|\),
所以\(A_{k'}\)也是\(S_k\)的一个最大兼容活动子集。
若贪心策略为选择持续时间最短者、最早开始者等,均不能保证\(A_{k'}\)兼容的性质
16.1-4
int *GREEDY_SOLUTION_ONE(int *s, int *f, bool *visited) { int n = s.length(); int a ; for (int i = 1; i <= n; i++) { if (!visited[i]) { a[0] = i; break; } } int cnt = 0; int k = a[0]; for (int m = k+1; m <= n; m++) { if (s[m] >= f[k]) { a[++cnt] = m; k = m; visited[m] = true; } } return a; } int GREEDY_SOLUTION_ONE(int *s, int *f) { int n = s.length(); bool visited[n+1]; for (int i = 1; i <= n; i++) visited[i] = false; int cnt = 0; while (n > 0) { int res ; res = GREEDY_ACTIVITY_SELECTOR(s, f, visited); int len = res.length(); for (int i = 0; i < len; i++) { visited[res[i]] = true; } n -= len; cnt++; } return cnt; }
贪心策略:找出子问题的最大兼容活动子集涂上相同的颜色。
16.1-5
在输入中添加哨兵:
\(activity = <a_0, a_1, ..., a_n, a_{n+1}>\)
其中\(a_0.start = 0, a_0.finish = 0\)
\(a_{n+1}.start\) = INT_MAX, \(a_{n+1}.finish\) = INT_MAX
#include <stdio.h> #include <limits.h> int n = s.length(); int _v[n+2][n+2]; int _e[n+2][n+2]; void solution(int *s, int *f, int *v) { for (int i = 0; i <= n; i++) { _v[i][i+1] = 0; } for (int l = 2; l <= n+1; l++) { for (int i = 0; i <= n-l+1; i++) { j = i+l; int max = -1; for (int k = i+1; k < j; k++) { int temp = _v[i][k] + _v[k][j] + v[k]; if (temp > max) { max = temp; _e[i][j] = k; } } } } }
16.2
16.2-1
证明:
即证明命题:设\(a_k\)是剩余物品中\(v_i/w_i\) 最大的物品,则对于这个子问题,\(a_k\)必在最优解中。
证明:否则假设存在\(a_j\)\((w_j \leq w_k)\)使得\(\sum\)\(v_i\)更大
由于\(v_k/w_k \geq v_j/w_k\)
所以\(v_k \geq v_j\)
所以矛盾
16.2-2
typedef struct { int v; int w; }Product; bool CompareByW(Product a, Product b) { return a.w < b.w; } int solution(vector<Product> products, int weight) { sort(products.begin(), products.end(), CompareByW); int e[weight+1]; int p[weight+1]; for (int i = 0; i <= weight; i++) e[i] = 0; for (int i = 1; i <= weight; i++) { for (int j = 0; weight - products[j].w >= 0; j++) { int temp = products[j].v + e[weight - products[j].w]; if (temp > e[i]) { e[i] = temp; p[i] = j; } } } return e[weight]; }
16.2-3
typedef struct
{
int v;
int w;
}Product;
bool CompareByW(Product a, Product b)
{
return a.w < b.w;
}
int solution(vector<int> products, int weight)
{
sort(products.begin(), products.end(), CompareByW);
int max = 0;
int k = -1;
for (int i = 0; i < products.size(); i++)
{
if ((weight = weight - products[i].w) >= 0)
{
max += products[i].v;
int k = i;
}
else break;
}
return max;
}
[/code]
证明:
设此贪心策略下装入的商品按w递增排序为\(p_1, p_2, ..., p_m\)
假设它不是最优解,则存在最优解下装入的商品按w递增排序为\(q_1, q_2, ..., q_{m'}\)
由贪心的性质得:
$\sum_{1\leq i \leq m} p_i.w $ \(\leq\) \(\sum_{1\leq i \leq m'}q_i.w\)
$\sum_{1\leq i \leq m} p_i.v $ \(\geq\) \(\sum_{1\leq i \leq m'}q_i.v\)
矛盾
16.2-4
int solution(int *places, int m) { int cnt = 0; int dis = 0; int n = places.length(); for (int i = 0; i < n; i++) { dis += places[i]; if (dis > m) { dis = 0; cnt++; i--; } } return cnt; }
证明:
设此贪心策略下的补充水的地点依次为\(p_1, p_2, ..., p_m\)
假设它不是最优解,则存在最优解下的地点依次为$q_1, q_2, ..., q_{m'}$
且\(m' < m\)
由于任意两取水点之间距离\(dis \leq m\)
所以\(\sum _{1\leq i \leq m'}\)\(dis(q_i)\) < \(\sum _{1\leq i \leq m}\)\(dis(p_i)\) = whole distance
矛盾
16.2-5
int solution(float *x) { sort(x); int n = x.length(); int pos ; int cnt = 0; for (int i = 0; i < n; i++) { pos[cnt++] = i; float up = x[i]+1; while (y[i] <= up) { i++; } } return cnt; }
证明:
最优子结构:
先对点集{x}得到{y}.\(S_{ij}\)表示以\(y_i\)为起点,\(y_j\)为最后一个点的单位长度区间集。设\(S_{mn}\)\(\subset\)\(S_{ij}\)
用c[i,j]表示集合\(S_{ij}\)的最优解大小。
则有递归式:
c[i,j] = \(min_{S_{mn}\subset S_{ij}}\){c[i,m]+c[n,j]+1}
假设贪心策略下的结果[p1, p1+1], ..., [\(p_m, p_m+1\)]不是最优解,则存在最优解[q1, q1+1], ..., [\(q_{m'}\), \(q_{m'}+1\)]
且m' < m
又\(p_m+1 - p_1 \geq y_j - y_i\) 但 \(p_{m-1}+1-p_1 < y_j - y_i\)
可知矛盾
16.2-6
typedef struct { int v; int w; float l; }Product; bool CompareByL(Product a, Product b) { return a.l > b.l; } float solution(vector<product> products, int weight) { sort(products.begin(), products.end(), CompareByL); int n = products.size(): float max = 0; for (int i = 0; i < n; i++) { if (weight - products[i].w >= 0) { max += products[i].v; weight -= products[i].w; } else { max += products[i].l*weight; break; } } return max; }
16.2-7
#include <cmath> double solution(vector<int> a, vector<int> b) { sort(a.begin(), a.end()); sort(b.begin(), b.end()); double max = 0; int n = a.size(): for (int i = 0; i < n; i++) { max += pow(a[i], b[i]); } return max; }
证明:
\(lg\)\(\prod_1^n a_i^{b_i}\) = \(\sum_1^n b_ilga_i\)
由排序不等式可得,此算法正确。
16.4
16.4-1
证明:
1、S是一个有限集
2、\(I_k\)满足遗传性。
设任意集合B\(\subset\)A,|B| \(\leq\) k
对于任意A\(\subset\)B, 有A \(\subset\)\(I_k\)
3、满足交换性
设\(A \in I_k 、B \in I_k, |A| < |B|\), 存在\(x \in B-A\) ,
|{x} \(\bigcup A|\)\(\leq\)|B|
所以|x \(\bigcup\) A| \(\in\) \(I_k\)
16.4-2
证明:
1、S是一个有限集
2、\(I\)是可遗传的
对于任意B\(\in I\)且A\(\subset\)B,有B中的列是线性无关的。
所以A中的列也是线性无关的,所以A\(\in I\)
3、\(M\)满足交换性。
对于任意\(A \in I, B \in I, |A| < |B|\),则\(A \subset B\)
所以必存在某个元素\(x \in B-A\), 使得\(A \bigcup {x} \in I\)
16.4-3
证明:
1、S是一个有限集
2、\(I'\)是可遗传的
对于任意\(B' \in I'且A' \subset B'\), 存在最大独立子集\(A \in I\), 使得\(A \subset S-B'\)
又\(S-B' \subset S-A'\)
所以\(A \subset S-A'\)
3、\((S,I')\)是可交换的
对于任意\(A' \in I', B'\in I', |A'| < |B'|\)
若\(A' \subset B'\),由性质2得显然成立。
否则,假设存在最大独立子集\(C_1, C_2 \in I\),使得\(C_1 \subset S-A', C_2 \subset S-B'\)
转载于:https://www.cnblogs.com/KarlZhang/p/8490616.html
- 算法导论学习笔记-第十六章-贪心算法
- 活动选择问题(算法导论第十六章贪心算法)
- 算法导论第十六章贪心算法-0-1背包问题
- 动态规划解决——装配线调度(算法导论第15章)
- 算法导论之散列表
- 【python菜鸟日记】-03算法导论-归并排序
- 算法导论-9.3-6算法导论-9.3-6 .
- 算法导论-5.基本数据结构
- 散列表---算法导论第十一章 Hash Tables
- 图的广度优先搜索----算法导论
- 算法导论--归并排序
- 算法导论第一天学习笔记
- 算法导论——lec 11 动态规划及应用
- 算法导论之排序算法学习
- 学习算法导论
- 对区间的模糊排序(原题算法导论第三版思考题7-6)
- 矩阵链乘法(最小乘法数) (动态规划算法实现)算法导论p201
- 麻省理工算法导论公开课(5)--How fast can we sort?
- 算法导论_15.5 最优二叉查找树
- 算法导论 4.1-2