前言:这门课程教材为清华出版社的算法设计与分析第二版,这本书上的代码,以及学校实验,实验报告,PTA实验编程题等资源,我都会放在Gitee仓库中。
new(albert)/算法分析与设计
/*
* @Description:
* @version:
* @Author:
* @Date: 2021-04-24 16:06:25
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-04-24 18:28:26
*/
// 重点理解子集的判断和处理
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
int i, j, k, min, temp, n;
int D[20][20];
cout << "Number of vertices is:";
cin >> n;
int b = (int)pow(2, n - 1);
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
cin >> D[i][j];
int **Route = (int **)calloc(n, sizeof(int *));
int **Mat = (int **)calloc(n, sizeof(int *));
for (i = 0; i < n; i++)
{
Route[i] = (int *)calloc(b, sizeof(int));
Mat[i] = (int *)calloc(b, sizeof(int));
}
for (i = 0; i < b; i++)
for (j = 0; j < n; j++)
{
Route[j][i] = -1;
Mat[j][i] = -1;
}
for (i = 0; i < n; i++) //初始化第0列
Route[i][0] = D[i][0];
for (i = 1; i < b - 1; i++)
for (j = 1; j < n; j++) //依次进行第i次迭代
if (((int)pow(2, j - 1) & i) == 0) //子集V[i]不包含j,则进行处理,否则还是默认值
{
min = 999;
// 再从这个子集中选出一个结点来计算D[j][k]+dis[k][i-那个点]
for (k = 1; k < n; k++)
if ((int)pow(2, k - 1) & i)
{
temp = D[j][k] + Route[k][i - (int)pow(2, k - 1)];
if (temp < min)
{
min = temp;
Route[j][i] = min;
Mat[j][i] = k; //局部最优决策
}
}
}
min = 999;
// 处理最后一列,得到最后的最优解
for (k = 1; k < n; k++)
{
temp = D[0][k] + Route[k][b - 1 - (int)pow(2, k - 1)];
if (temp < min)
{
min = temp;
Route[0][b - 1] = min; //最优解
Mat[0][b - 1] = k;
}
}
cout << "Length of shortest path:" << Route[0][b - 1] << endl; //最短路径长度
cout << "The shortest path is:"
<< "1";
for (i = b - 1, j = 0; i > 0;)
{
j = Mat[j][i];
i = i - (int)pow(2, j - 1);
cout << "->" << j + 1;
}
cout << "->1" << endl;
for (i = 0; i < n; i++)
{
for (j = 0; j < b; j++)
cout << Route[i][j] << "\t";
cout << endl;
}
free(Route);
free(Mat);
system("pause");
return 0;
}
/*
4
0 3 6 7
5 0 2 3
6 4 0 2
3 7 5 0
*/
/*
* @Description: 01背包问题
* @version:
* @Author:
* @Date: 2021-04-24 16:06:25
* @LastEditors: Please set LastEditors
* @LastEditTime: 2021-04-24 16:15:00
*/
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
// V[n+1][C+1]存放结果,V[i][j]表示将前1个物品装入容量为j的背包能获取的最大值(不一定全部物品装入)
// x[n]表示该物品是否装入背包
// C表示背包的容量
int KnapSack(vector<int> w, vector<int> v, const int C, vector<int> &x)
{
int i, j;
const int n = w.size();
// 插入两个无用数据,使得两个数组的有效数据是1-n
w.insert(w.begin(), 0);
v.insert(v.begin(), 0);
int V[n + 1][C + 1];
// 初始化第0列,表示前i个物品放入容量为0的背包最大价值是0
for (i = 0; i <= n; i++)
V[i][0] = 0;
// 初始化第0行,表示0个物品放入容量为j的背包,最大价值是0
for (j = 0; j <= C; j++)
V[0][j] = 0;
for (i = 1; i <= n; i++)
for (j = 1; j <= C; j++)
// 当前的容量不能放第i个物品,则最大价值就是放前i-1个物品进相同容量背包的最大值
if (j < w[i])
V[i][j] = V[i - 1][j];
// 如果能放入这个物品,则从(相同容量放入前i-1物品的最大价值)与
// (当前容量-物品重量的背包放入前i-1物品的最大值+这个物品价值)
// (就是不放这个物品之前的最大价值加上这个物品的价值)
// 或者是说,这个容量不放这个物品的最大值 与 放入这个物品的最大值
// (要放入这个物品,就要给这个物品留w[i]的空间,所以要用V[i-1][j-w[i]]+v[i])
// 两者较大
else
V[i][j] = max(V[i - 1][j], V[i - 1][j - w[i]] + v[i]);
// 从V[n][C]开始 至 i == 1
for (j = C, i = n; i > 0; i--)
{
// 当前情况的最大值与相同容量下放i-1个物品的最大值比较,若大了,说明第i个物品放入了
// 标记x[i]=1,然后下一轮去找 V[i - 1][j - w[i]],相当于决策过程的逆过程(回溯)
if (V[i][j] > V[i - 1][j])
{
x[i] = 1;
j = j - w[i];
}
else
x[i] = 0;
}
// 输出决策矩阵
for (int i = 1; i <= 5; i++)
{
for (int j = 1; j <= 5; j++)
cout << V[i][j] << "\t";
cout << endl;
}
return V[n][C];
}
int main()
{
vector<int> w{2, 2, 6, 5, 4};
vector<int> v{6, 3, 5, 4, 6};
vector<int> x(v.size() + 1, 0);
int result = KnapSack(w, v, 10, x);
for (int i = 1; i <= 5; i++)
cout << x[i] << " ";
cout << endl;
cout << result << endl;
system("pause");
return 0;
}