(:新人报道:) 我处于初窥算法的状态,书路漫漫。望诸君多多指点江山,我愿洗耳恭听。
“贪心法,又称贪心算法、贪婪算法、或称贪婪法,是一种在每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是最好或最优的算法。[1]比如在旅行推销员问题中,如果旅行员每次都选择最近的城市,那这就是一种贪心算法。
贪心算法在有最优子结构的问题中尤为有效。最优子结构的意思是局部最优解能决定全局最优解。简单地说,问题能够分解成子问题来解决,子问题的最优解能递推到最终问题的最优解。
贪心算法与动态规划的不同在于它对每个子问题的解决方案都做出选择,不能回退。动态规划则会保存以前的运算结果,并根据以前的结果对当前进行选择,有回退功能。
贪心法可以解决一些最优化问题,如:求图中的最小生成树、求哈夫曼编码……对于其他问题,贪心法一般不能得到我们所要求的答案。一旦一个问题可以通过贪心法来解决,那么贪心法一般是解决这个问题的最好办法。由于贪心法的高效性以及其所求得的答案比较接近最优结果,贪心法也可以用作辅助算法或者直接解决一些要求结果不特别精确的问题。”
——摘自维基百科
那么问题来了:
“旅行推销员问题(最短路径问题)(英语:Travelling salesman problem, TSP)是这样一个问题:给定一系列城市和每对城市之间的距离,求解访问每一座城市一次并回到起始城市的最短回路。”
——摘自维基百科
简单说明鄙人理解的意思:城市之间两辆互通,然后从某个城市出发,求出最短路径,同时终点也是起点。
那么——
根据贪心的思路,每次选择城市的时候,选择最短距离(这里注意,要将出发城市即起点讨论范围,避免error),直到回到起点;
于是——
数据结构:定义了一个二维数组,一个一维数组。二维数组用于存储城市之间的距离,利用一维数组下标判断该城市是否被访问过。
算法:具体见代码 =..=(ps:感觉不会说明 /笑哭)
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX 5000
int distance[MAX][MAX];
int city[MAX];
int main(int argc, char const *argv[])
{
int n,length,count;
scanf("%d",&n);
count = n;
srand((unsigned)time(0));
for (int i = 0; i < n; ++i){
for (int j = i; j < n; ++j)
if( i != j){
distance[i][j] = rand()%9+1;
distance[j][i] = distance[i][j]; //用随机函数生成数组,最大值为9
}
else
distance[i][j] = 20;
}
/*for (int i = 0; i < n; ++i){
for (int j = 0; j < n; ++j){
printf("%d\t", distance[i][j]);
}
printf("\n");
}*/ //输出距离数组
int temp_distance = 0,next;
int cur,i= 0;
scanf("%d",&cur); //cur获得起点城市,next存储下个城市
int final = cur;
n--; //执行n-1次寻找城市。因为最后一次必定是回到原点
while(n--){
temp_distance = 99;
for (int j = 0; j < count; ++j)
{
if( j != final && distance[cur][j] < temp_distance && !city[j] ){
//寻找条件:不能回到原点,城市未被访问,路径最短
temp_distance = distance[cur][j];
next = j; //获取临时的下一个城市
}
}
i ++;
city[next] = 1;
cur = next;
length += temp_distance; //更新当前状态:将城市设置为被访问,cur=next,前往下一个城市
//printf("%d:%d\t|%d\n",i,cur,length ); 输出每一步状态
}
printf("%d:%d\t|%d\n",count,final,length+= distance[final][cur] );
return 0;
}