小H的旅游计划2
题目描述
题目分析
解决方案
题目描述
Z王国有若干个城市(编号从1开始),每两个城市之间都有一条道路.
由于Z王国的特殊政策,每个城市只允许游客访问一次.
请你帮助小H规划一条旅行路线,使得小H可以访问所有城市,并且每个城市只访问一次
由于城市数量过多,小H放宽了要求,最终的路径长度不需要最短,只要优于小H的可接受值即可
然而我们并不知道小H的可接受值是多少,因此我们能做的就是尽可能缩短路径长度
输入
第一行是一个样例编号t,没有实际作用,只需要原封不动输出即可
第二行是一个整数n(1<=n<=50),表示城市的个数
接下来是一个n*n的对称矩阵,元素dis[i,j]表示i城市与j城市间道路的长度(1<=dis[i,j]<=10000,dis[i,i]=0,dis[i,j]=dis[j,i])
输出
第一行输出样例编号t
第二行输出n个空格分开的整数,代表你的尽可能短的路径
输入样例:
0
16
0 12 6 18 9 7 2 15 2 10 2 3 14 3 8 14
12 0 7 17 13 15 10 21 10 5 24 22 13 23 22 20
6 7 0 22 11 21 13 22 24 21 25 17 16 3 3 23
18 17 22 0 20 25 12 4 4 1 16 11 3 7 7 21
9 13 11 20 0 19 20 15 23 19 19 1 4 7 24 1
7 15 21 25 19 0 4 6 13 21 25 16 12 21 12 23
2 10 13 12 20 4 0 17 8 8 16 9 21 17 2 21
15 21 22 4 15 6 17 0 8 6 21 11 12 19 23 5
2 10 24 4 23 13 8 8 0 7 14 19 20 24 20 4
10 5 21 1 19 21 8 6 7 0 6 25 18 2 2 4
2 24 25 16 19 25 16 21 14 6 0 10 8 1 25 22
3 22 17 11 1 16 9 11 19 25 10 0 3 22 2 12
14 13 16 3 4 12 21 12 20 18 8 3 0 18 20 8
3 23 3 7 7 21 17 19 24 2 1 22 18 0 3 25
8 22 3 7 24 12 2 23 20 2 25 2 20 3 0 19
14 20 23 21 1 23 21 5 4 4 22 12 8 25 19 0
输出样例:
0
2 10 14 11 1 7 6 8 13 4 9 16 5 12 15 3
(提示:每组样例都设定了一个可接受值,你的解只要小于这个可接受值就可以通过.采用任何方法都可以
.推荐尝试分支限界,实在解不出来的话就贪心吧:-)
题目分析
由于城市的数量较大,如果直接用递归的话求最短路径的话很容易超时。以下提供一个贪心算法。分别以每一个城市作为起点,每一次都前往与当前城市距离最近的城市。每一个城市作为起点均可求得一条路径及其长度,最后通过比较取长度最小的路径输出即可。
解决方案
#include <iostream>
#include <vector>
using namespace std;
int d[51][51],visit[51]={0},n;
vector<int>path[51]; //存储以每一个城市为起点的路径
int seek(int start,int now,int cnt){ //起点,当前城市,已旅游过的城市数量
if(cnt==n-1) //已遍历完,不需要再往下走
return 0;
visit[now]=1; //标记已访问
int city=0,len=20000;
for(int i=1;i<=n;i++){ //找与当前城市最近的城市
if(!visit[i]&&d[now][i]<len){
city=i;
len=d[now][i];
}
}
path[start].push_back(city); //记录路径
return len+seek(start,city,cnt+1); //返回路径长度
}
int main(){
int example;
cin>>example>>n;
for(int i=1;i<=n;i++){
path[i].push_back(i);
for(int j=1;j<=n;j++)
cin>>d[i][j];
}
int start=0,length=seek(1,1,0);
for(int i=2;i<=n;i++){
for(int j=1;j<=n;j++)
visit[j]=0; //还原现场
int d1=seek(i,i,0);
if(d1<length){ //找最短长度路径
length=d1;
start=i;
}
}
cout<<example<<endl;
for(int i=0;i<path[start].size();i++) //输出路径
cout<<path[start][i]<<' ';
return 0;
}