贪心算法介绍
贪心算法总是做出在当前看来最好的选择,也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择,虽然贪心算法不能对所有问题都得到整体最优解,但是对许多问题它能产生整体最优解.
贪心算法的基本要素
贪心选择性质
它是指所求问题的整体最优解可以通过一系列局部最优的选择来达到。这是贪心算法一个非常重要的要素,也是和动态规划算法的主要区别,在贪心算法中,仅在当前状态下做出最好选择,然后再去解做出这个选择后产生的相应的子问题,贪心算法所做出的贪心选择可以依赖于以往所做过的选择,但绝不依赖将来所做的选择,也不依赖于子问题的解,因此贪心算法通常以自顶向下的方式进行,每做出一次贪心选择就将问题规模缩小.
最优子结构性质
一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质
单源最短路径
一、问题
计算从源到所有其他各个顶点的最短路径长度
二、 基本思想
设置已访问顶点集合visted,并不断贪心选择扩充这个集合,直到所有都是true,初始的时候,visted只有source顶点置为true,其余均为false,然后更新dist[i]存放了source顶点到i顶点的距离,若不是直接相连,则是INT_MAX,然后开始从第一个顶点开始遍历,然后更新dist,记录下它的下边和权值,将visted数组对应的下标置为true,代表已经找到了,然后更新dist数组,需要注意的是更新的前提是:
1.该顶点还没有访问(也就是还没有找到source顶点到此顶点的最短路径)
2.确保找到的这个权值最小顶点和此顶点有直接相连的边
3.权值只和小于此顶点当前的值
path[i]数组记录了从源到顶点i相应的路径,初始时给path数组全部赋值为source顶点,在算法中更新路径长度时候,只要matrix[min_cost_index][ j ] + min_cost小于 dist[j],
就让path[j] = min_cost_index,当算法终止的时候,就可以根据path数组找到从源到i的最短路径上每一个定点的前一个顶点,从而找到路径
三、代码实现:
#include<iostream>
using namespace std;
int matrix[100][100]; //邻接矩阵
bool visited[100]; //标记数组
int dist[100]; //源点到顶点i的最短距离
int path[100]; //记录最短路的路径
int source; //源点
int vertex_num; //顶点数
int arc_num; //边数
void Dijkstra(int source)
{
memset(visited, 0, sizeof(visited+1)); //初始化标记数组
visited[source] = true;
for (int i = 1; i <= vertex_num; i++)
{
dist[i] = matrix[source][i];
path[i] = source;
}
int min_cost; //权值最小
int min_cost_index; //权值最小的下标
for (int i = 1; i <= vertex_num; i++) //找到源点到另外vertex_num-1个点的最短路径
{
min_cost = INT_MAX;
for (int j = 1; j <= vertex_num; j++)
{
if (visited[j] == false && dist[j] < min_cost) //找到权值最小
{
min_cost = dist[j];
min_cost_index = j;
}
}
visited[min_cost_index] = true; //该点已找到,进行标记
for (int j = 1; j <=vertex_num; j++) //更新dist数组
{
if (visited[j] == false &&
matrix[min_cost_index][j] != INT_MAX && //确保两点之间有边
matrix[min_cost_index][j] + min_cost < dist[j])
{
dist[j] = matrix[min_cost_index][j] + min_cost;
path[j] = min_cost_index;
}
}
}
}
//单源最短路径
int main()
{
cout << "请输入图的顶点数(<100):";
cin >> vertex_num;
cout << "请输入图的边数:";
cin >> arc_num;
for (int i = 0; i <= vertex_num; i++)
for (int j = 0; j <= vertex_num; j++)
matrix[i][j] = INT_MAX; //初始化matrix数组
cout << "请输入弧的信息:\n";
int u, v, w;
for (int i = 0; i < arc_num; i++)
{
cin >> u >> v >> w;
//有向图
matrix[u][v] = w;
}
cout << "请输入源点(<" << vertex_num << "):";
cin >> source;
Dijkstra(source);
for (int i = 1; i <= vertex_num; i++)
{
if (i != source)
{
cout << source << "到" << i << "最短距离是:" << dist[i] << ",路径是:" << i;
int t = path[i];
while (t != source)
{
cout << "--" << t;
t = path[t];
}
cout << "--" << source << endl;
}
}
system("pause");
return 0;
}
运行示例: