2017-03-04 天天爱旅游

Description

天天突发奇想, 要去 G 地, 于是他搞来了一张地图, 看怎么走才好。
地图上有很多城市, G 地也是一座城市。 每两座城市之间都可能有直达方法, 也有可能 两座城市之间并不能直接相通, 而要通过其他的城市转达。 对于两个城市之间的直达方法, 需要一定的时间, 当然, 如果从 A 城市到 B 城市的直达方法需要 T 时间, 那么从 B 城市到 A 城市的直达方法也是 T 时间。
天天想要用最短的时间到达 G 地, 但是有个问题, 他发现, 地图上有些城市对他很有 吸引力。 所以他要在经过这些城市的基础上时间最短。
天天已经用 1、 2、 3、 4、 5……n 标记了他可能经过的城市( 1 代表出发地, n 代表 G 地), 但是眼花缭乱的地图让他感到烦恼。 他请你来解决这个问题, 告诉他最小需要多少时 间到达 G 地。
Input

第一行是三个正整数 n 和 m, t, n 表示总共有多少个城市( 包括出发地和 G 地), 城市 数不会超过 200 个; m 是城市的直达路线数( 1<=m<=20000), t 表示一定去的城市数 0<=t<=10 ( 不包括出发地和 G 地)。
接下来一行有 t 个整数, 表示一定要去的城市。
接下来 m 行, 每行包含三个正整数, 前两个数表示分别代表一个城市, 第三个数是这 两个城市之间的直达时间。 直达时间不会超过 1000000。

Output

输出一个数, 题目要求的得最短时间。

Sample Input

5 10 2
2 3
1 2 5
1 3 45
1 4 61
1 5 81
2 3 9
2 4 91
2 5 4
3 4 74
3 5 42
4 5 61

Sample Output

27

数据范围:

1<=n<=200
1<=m<=20000
0<=t<=10

Source

最短路 ,搜索, 动态规划, 状态压缩

Solution

超超超超级类似与售货员的难题,先走一遍floyed找最短路,然后dfs,找到ans最小值即可

求最短路,优秀的暴力有30左右

Code

#include <cstdio>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
int road[201][201],des[201],ans;
bool vis[201];
int n,m,t;
void dfs(int x,int dis,int num)//现在所在城市,从起始点到这个城市已经走过的距离,从起始点到这个城市已经到过的城市数量
  {
    if(num==t)//如果到过的城市已经符合要求
      {
    if(dis+road[x][n]<ans)//如果可以更新答案
      ans=dis+road[x][n];//更新答案
    return ;
      }
    for(int i=1;i<=t;i++)//枚举城市
      {
    if(vis[i])//如果可以到
      {
        vis[i]=false;//标记为到过
        dfs(des[i],dis+road[x][des[i]],num+1);//更改现在所在城市,已走距离,和已到城市数量
        vis[i]=true;//回溯
      }
      }
  }
int main()
{
  freopen("starhder.in","r",stdin);
  freopen("starhder.out","w",stdout);
  ans=1000000000;
  scanf("%d%d%d",&n,&m,&t);
  for(int i=1;i<=t;i++)
    scanf("%d",&des[i]);
  int x,y,d;
  memset(road,289,sizeof(road));
  for(int i=1;i<=m;i++)
    {
      scanf("%d%d%d",&x,&y,&d);
      //    if(d<road[x][y])
      road[x][y]=d,road[y][x]=d;
    }
  for(int k=1;k<=n;k++)
    for(int i=1;i<=n;i++)
      for(int j=i+1;j<=n;j++)//floyed求最短路
    {
      if(i!=j&&road[i][k]+road[k][j]<road[i][j])
        road[i][j]=road[j][i]=road[i][k]+road[k][j];
    }
  memset(vis,true,sizeof(vis));
  dfs(1,0,0);
  printf("%d\n",ans);
  return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值