算法设计与分析-上机实验10
1、已知一个加权有向图(为了计算方便,假设编号为1的顶点是入度为0的源点,编号为n的顶点是出度为0的汇点,图中的顶点从1开始编号),要求计算图中从源点出发到汇点的最短距离及其对应的路径(逆向输出)。
输入
第1行输入两个整数,分别表示图G中顶点数n和边数m。
第2 - m+1行每行输入三个整数,分别表示顶点i和顶点j的编号以及由这两个顶点的有向边上的权。
输出
第1行输出源点到汇点的最短路径距离。
第2行输出汇点到源点的逆向最短路径。
样例输入
5 7
1 2 10
1 4 30
1 5 100
2 3 50
3 5 10
4 3 20
4 5 60
样例输出
60
5 3 4 1
代码
// By SnowDream
#include<bits/stdc++.h>
using namespace std;
const int MaxSize = 100;
int n; // 图中的顶点个数
int m; // 图中的边的个数
vector<vector<int>> a(MaxSize, vector<int>(MaxSize, INT_MAX)); // 邻接矩阵
vector<int> label(MaxSize, 0); // 存储源点到其余顶点最短路径上的最后一个顶点编号
vector<int> d(MaxSize, INT_MAX); // 存储从源点出发到其余各个顶点的最短距离
void CreateGraph() {
int u, v, w;
for (int i = 1; i <= n; i++) { // 初始化邻接矩阵对角线
a[i][i] = 0;
}
for (int i = 0; i < m; i++) { // 输入边信息填写有向图的邻接矩阵
cin >> u >> v >> w; // 边的信息包括顶点1和顶点2的编号以及它们之间的距离
a[u][v] = w;
}
}
void snow() { // 从顶点1开始
queue<pair<int, int>> q; // 使用STL中的队列,队列元素是一个整数对,表示顶点编号和当前距离
q.push({1, 0}); // 构造根节点
while (!q.empty()) {
auto e = q.front();
q.pop();
int i = e.first;
int length = e.second;
for (int j = 1; j <= n; j++) {
if (a[i][j] < INT_MAX && length + a[i][j] < d[j]) {
d[j] = length + a[i][j];
label[j] = i;
q.push({j, d[j]});
}
}
}
}
int main() {
cin >> n >> m;
CreateGraph();
d[1] = 0;
label[1] = 0;
snow();
cout << d[n] << endl;
for (int i = n; i != 0; i = label[i]) {
cout << i << " ";
}
return 0;
}
2、给定n种物品和一背包。物品i (1≤i≤n) 的重量是wi (wi > 0),其价值为vi (vi > 0),背包的容量为c (c > 0)。问应如何选择装入背包的物品,使得装入背包中物品的总价值最大?
输入
第1行输入两个整数分别表示物品的数量和背包容量。
第2行输入n个整数分别表示每个物品的重量。
第3行输入n个整数分别表示每个物品的获利。
输出
第1行输出整个背包的最大获利。
样例输入
3 50
45 25 25
28 15 15
样例输出
30
代码
// By SnowDream
#include<bits/stdc++.h>
using namespace std;
const int MaxSize = 100;
int n; // 物品数量
int c; // 背包容量
vector<int> w(MaxSize); // 各个物品的重量,0号单元不用
vector<int> v(MaxSize); // 各个物品的价值,0号单元不用
vector<int> bestx(MaxSize); // 当前最优解,0号单元不用
int bestv = 0; // 当前最优值
struct QNode {
int cw; // 当前已放物品的重量
int cv; // 当前已放物品的获利
int i; // 当前在解空间树中的层数,假设根结点是第1层
vector<int> x; // 当前解向量
};
void snow() {
queue<QNode> q;
// 构造根结点
QNode e;
e.cw = 0;
e.cv = 0;
e.i = 1;
e.x.resize(n + 1, 0); // 初始化解向量
q.push(e);
while (!q.empty()) {
QNode current = q.front();
q.pop();
if (current.i == n + 1) { // 处理解空间树中的叶子结点
if (current.cv > bestv) {
bestv = current.cv;
bestx = current.x;
}
} else { // 处理解空间树中的非叶子结点
// 处理左孩子,要该物品
QNode leftChild = current;
leftChild.x[leftChild.i] = 1; // 选择当前物品
leftChild.cw += w[leftChild.i]; // 更新当前重量
leftChild.cv += v[leftChild.i]; // 更新当前价值
leftChild.i++; // 准备好进入下一层
if (leftChild.cw <= c) { // 如果满足约束条件
q.push(leftChild);
}
// 处理右孩子,不要该物品
QNode rightChild = current;
rightChild.i++; // 准备好进入下一层
q.push(rightChild);
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> c;
for (int i = 1; i <= n; i++) {
cin >> w[i];
}
for (int i = 1; i <= n; i++) {
cin >> v[i];
}
snow();
cout << bestv << endl;
return 0;
}