XMUOJ·小H的旅游计划2

小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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泠然鸢鸣

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值