这是我参与8月更文挑战的第4天,活动详情查看: 8月更文挑战
算法设计与分析题目1: 带权无向图G=(V, E)
每个顶点v∈G都有权值w(v)
设U是V的子集
U为图G的顶点覆盖:对任意边(u, v)∈E,有u∈U or v∈U
最小权顶点覆盖:顶点权之和最小
算法:
对于给定带权无向图G,用优先队列式分支界限法,计算最小权顶点覆盖
输入:
第1行:n个顶点(编号从1...n),m条边
第2行:n个顶点的权重
下面m行:表示边
输出:
第1行:最小权顶点的权重之和
第2行:对应的顶点
核心代码及注释:
/* 淘汰掉i的相邻点权重之和<i本身权重的点 */
for (int i = 0; i < n; ++i) {
int sum = -w[i];
int num = 0;
for (int j = 0; j < n; ++j) {
if (G[i][j]) {
sum += w[j];//保存i的相邻点的权重和
store[i][num++] = j;//存i的相邻点
}
}
//如果i的相邻点权重和<i的权重,淘汰,此时还没将flag[4]淘汰
if (sum <= w[i])
flag[i] = 0;
}
for (int i = 0; i < n; ++i) {
if (!flag[i]) continue;//被淘汰的点跳过
//只有权值大的可能被淘汰
for (int j = i + 1; j < n; ++j) {
if (w[i] > w[j]) {
//若i给j全覆盖,i被淘汰
if (TF(j, i))
flag[i] = 0;
}
else {
//若j给i全覆盖,j被淘汰
if (TF(i, j))
flag[j] = 0;
}
}
}
for (int i = 0; i < n; ++i) {
if (!flag[i]) continue;//被淘汰的点跳过
int num = 0;
for (int j = 0; j < n; ++j)
if (flag[j] && G[i][j])
++num;
//必选
if (num == 1)
flag[i] = 2;
}
测试结果: 输入:
7 7
1 100 1 1 1 100 10
1 6
2 4
2 5
3 6
4 5
4 6
6 7
输出:
算法设计与分析题目2:
设计一个算法,求出无序整数数组中满足条件的最大乘积,给定一个无序数组,包含正数、负数和0,要求从中找出3个数的乘积,使得乘积最大,并且时间复杂度为O(n)、空间复杂度为O(1)。
核心代码及注释:
for(int i = 0; i < n; i++)
{
if(a[i] > max_1)
{
max_3 = max_2;
max_2 = max_1;
max_1 = a[i];
}
else if(a[i] > max_2)
{
max_3 = max_2;
max_2 = a[i];
}
else if(a[i] > max_3)
max_3 = a[i];
if(a[i] < min_1)
{
min_2 = min_1;
min_1 = a[i];
}
else if(a[i] < min_2)
min_2 = a[i];
}
mul_max1 = max_1 * max_2 * max_3;
mul_max2 = min_1 * min_2 * max_1;
res_max = mul_max1 > mul_max2?mul_max1:mul_max2;
测试结果:
输入:
输出:
算法思想:因为存在正数和负数的原因,要找出三个数的乘积最大者,可能的情况为三个最大正数的乘积,和两个最小的负数与一个最大的正数的乘积,故核心思想在于找出最大的三个数和最小的两个数。