C++ 图论应用:项目日程安排算法详解
C++ 图论应用:项目日程安排算法详解
本文将通过 C++ 代码实现项目日程安排算法,并用图论的思想,利用邻接矩阵,对用户输入的项目信息进行建图,并通过贪心算法对其进行染色,最终实现项目日程表的可视化输出。
代码解析
#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
#include <string.h>
#include <stdio.h>
#include <windows.h>
using namespace std;
int map[49] = { 0 };
void Create(int a[]) { //根据用户输入进行建图
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
if ((a[i] != a[j]) && (a[i] != 0) && (a[j] != 0)) {
map[(a[i] - 1) * 7 + (a[j] - 1)] = 1;
}
}
struct Node { //图结点
int index;//结点在矩阵中的行数即位置
int degree;//结点度数,用于根据从大到小的度数关系进行涂色
int mark;//结点染色标记
};
string name[] = { '标枪', '铅球', '铁饼', '100m', '200m', '跳远', '跳高' };
bool cmp(Node a, Node b) { //自定义'小于'
return a.degree > b.degree;
}
void Print(vector <int>mark, int n, vector <Node>node, int Mark) { //创建可视化图表
int a[10] = { 0 };//存储标记对应的项目数
int b = 0, c = 1;
for (int j = 0; j < mark.size(); j++) { //同一标记对应项目数的赋值
for (int i = 0; i < n; i++)
if (node[i].mark == mark[j])
a[j]++;
}
int max = a[0];
for (int j = 0; j < mark.size() - 1; j++) { //确定项目日程表中列数的最大值
if (a[j + 1] > max)
max = a[j + 1];
}
cout << ' _________________________________' << endl;//实现项目日程的可视化
for (int p = 0; p < Mark; p++) {
cout << ' | | | | |' << endl;
if (c == 1)
cout << '|' << '|';
else if (c == 2)
cout << '|' << '|';
else if (c == 3)
cout << '|' << '|';
else if (c == 4)
cout << '|' << '|';
else if (c == 5)
cout << '|' << '|';
for (int i = 0; i < n; i++) {
if (node[i].mark == c) {
cout << name[node[i].index] << ' |';
b++;
}
}
if (b < max)
for (int i = 0; i < max - b; i++)
cout << ' |';
b = 0;
c++;
cout << endl;
cout << ' ------------------' << endl;
}
}
int fillcolor(int map[], int n) { //涂色
cout << '邻接矩阵' << endl;
int Mark = 0;
vector<int>mark;//动态标记集
vector<Node>node;//动态结点集
node.resize(n);//为结点集分配空间
for (int i = 0; i < n; i++) { //统计图中结点的度
node[i].degree = node[i].mark = 0;//度数、标记均初始化为0
node[i].index = i;
for (int j = 0; j < n; j++) {
if (map[i * n + j] == 1)
node[i].degree++;
}
}
sort(node.begin(), node.end(), cmp);//将图结点降序排列
for (int i = 0; i < n; i++) {
for (int j = 0; j < mark.size(); j++) { //取染色集元素进行染色
if (node[i].mark == 0)
node[i].mark = mark[j];
for (int k = 0; k < n; k++) {
if ((map[node[i].index * n + k] == 1) && (node[k].mark == node[i].mark)) { //两结点相邻且颜色相同,取消标记
node[i].mark = 0;
break;
}
}
}
if (node[i].mark == 0) {
mark.push_back(++Mark);
node[i].mark = mark.back();
}
}
Print(mark, n, node, Mark); //创建可视化图表
return Mark;//返回所需场次
};
int main() {
cout << '各项目对应编号为:标枪(1),铅球(2),铁饼(3),100m(4),200m(5),跳远(6),跳高(7) ' << endl;
cout << '请依次将选手所报项目编号输入' << endl;
int a[3] = { 0 };
string b[5] = { '张三', '李四', '王五', '赵六', '李七' };
for (int i = 0; i < 5; i++) {
cout << '请输入 ' << b[i] << ' 所报项目编号:';
for (int j = 0; j < 3; j++) {
a[j] = cin.get() - 48;
if (j == 2 && a[j] != -38)
cin.get();
else if (a[j] == -38) {
a[j] = 0;
break;
}
}
Create(a);
}
for (int i = 0; i < 7; i++) {
for (int j = 0; j < 7; j++)
cout << map[i * 7 + j] << ' ';
cout << endl;
}
int n = fillcolor(map, 7);
cout << '将需要比赛' << n << '场' << endl;
system('pause');
}
难点处理
在完成题目的过程中,最难处理的问题是如何根据用户输入建立图结构。这个问题的解决方法是使用一个大小为 49 的一维数组来表示图的邻接矩阵,通过遍历用户输入的项目编号,将对应的图结点之间的关系标记为 1,表示相邻。这样就成功地建立了图结构。
代码解释
- 建立图结构:
- 使用一个大小为 49 的数组
map来表示图的邻接矩阵,其中map[i * 7 + j] = 1表示第i个项目和第j个项目需要在不同场次进行。 - 函数
Create(int a[])根据用户输入的项目编号建立邻接矩阵。
- 使用一个大小为 49 的数组
- 贪心染色算法:
- 使用
fillcolor(int map[], int n)函数进行图染色,该函数使用贪心算法对图结点进行染色,以确保相邻结点颜色不同。 - 函数首先统计每个结点的度数,并根据度数从大到小排序。
- 然后,对于每个结点,依次遍历已有的染色集,如果当前结点与已染色结点不相邻,则使用该颜色对当前结点进行染色,否则继续尝试其他颜色。
- 如果当前结点没有找到合适的颜色,则使用新的颜色对当前结点进行染色,并将该颜色加入染色集中。
- 使用
- 可视化输出:
- 函数
Print(vector <int>mark, int n, vector <Node>node, int Mark)使用一个二维数组来存储染色结果,并通过循环遍历数组,将染色结果输出到屏幕。 - 输出格式为:将每个项目名称列出,并在其下方用 '|' 连接,同一场次的项目用相同的 '|' 连接,不同的场次用不同的 '|' 连接,并通过空格调整格式,以实现可视化效果。
- 函数
总结
本文详细解析了如何利用 C++ 图论算法解决项目日程安排问题,并通过实例代码演示了算法的实现过程。希望本文能帮助读者理解图论算法在实际应用中的作用。
原文地址: https://www.cveoy.top/t/topic/fwVa 著作权归作者所有。请勿转载和采集!