哈理工 oj 2122 旅行(map + 最短路dij算法)

本文介绍了一个旅行场景下的路径规划问题,旨在寻找从起点到终点所需的最少费用路径。通过使用Dijkstra算法实现,解决了旅行者在有限预算内的最优路径选择问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

旅行
Time Limit: 1000 MSMemory Limit: 32768 K
Total Submit: 18(6 users)Total Accepted: 3(3 users)Rating: Special Judge: No
Description

04.24,和Sakura去东京天空树,世界上最暖和的地方天空树的顶上。”

04.26,和Sakura去明治神宫,有人在那里举办婚礼。”

04.25,和Sakura去迪士尼,鬼屋很可怕,但是有Sakura在,所以不可怕。”

Sakura最好了。”

                                    ——江南 《龙族》

 

绘梨衣和路明非今天要从迪士尼前往天空树,但他们的钱不多了,所以能省则省,他们现在有一个地图上面有n个景点和m条景点之间的路,每条路坐车都需要一定的钱数,现在他们求助于你,请你帮他们计算下从当前地点到目的地最少需要的钱数。

Input

有多组数据,每组数据第一行有两个数字2<=n<=300001<=m<=30000

接下来n行输入n个地名。

接下来m行每行有两个字符串(长度不超过20)和一个数字,代表两地之间的坐车的费用。

接下来一行输入两个字符串分别代表起点和终点。

Output

一个int数代表最少需要的钱数。

数据保证不会超过int型范围。

Sample Input
2 1
disney
TokyoSkyTree
disney TokyoSkyTree 1
disney TokyoSkyTree
Sample Output
1
Source

2014暑假集训练习赛(7月19日)

看到 理工题目上 这个题目做的人没几个  ,就看看是什么玩意儿~!~

#include<iostream>
#include<sstream>
#include<algorithm>
#include<cstdio>
#include<string.h>
#include<cctype>
#include<string>
#include<cmath>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
using namespace std;
const int maxn=30003;
const int INF=0x1f1f1f1f;
int n,m;
//标记起始位置
string s;
string e;
map<string,int>cnt;//映射成节点编号

struct Edge
{
    int from,to,dist;
    Edge(int u,int v,int d):from(u),to(v),dist(d) {}
};
vector<Edge>edges;//存储边的结点信息
vector<int>G[maxn];//邻接表
bool done[maxn];   //标记是否访问过
int d[maxn];    //距离数组
struct heapnode //用于优先队列自定义
{
    int d,u;
    bool operator <(const heapnode rhs) const
    {
        return d > rhs.d;
    }
    heapnode(int dd,int uu):d(dd),u(uu) {}
};


void init()//初始化必不可少
{
    for(int i=0; i<n; i++)
        G[i].clear();
    edges.clear();
}

void addedge(int from,int to,int dist)
{
    edges.push_back(Edge(from,to,dist));
    int m = edges.size();
    G[from].push_back(m-1);
}

void dij( int s)
{
    priority_queue<heapnode>Q;
    for(int i=0; i<=n; i++)//初始化距离数组
        d[i]=INF;
    d[s]=0;
    memset(done ,0,sizeof(done));
    Q.push( heapnode(0,s) );
    while(!Q.empty())
    {
        heapnode x = Q.top();
        Q.pop();
        int u=x.u;
        if(u==cnt[e])
        {
            printf("%d\n",x.d);
            break;
        }
        if(done[u])continue;
        done[u] = true;
        for(int i=0; i<G[u].size(); i++)
        {
            Edge& e=edges[G[u][i]];//取出来一条邻接边
            if(d[e.to]>d[u]+e.dist)
            {
                d[e.to] = d[u] + e.dist;
                Q.push((heapnode(d[e.to],e.to)));
            }
        }
    }
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        int t=1;
        int ans=0;
        string str;
        init();
        for(int i=0; i<n; i++)
        {
            cin>>str;
            cnt[str]=t++;
        }
        for(int i=0; i<m; i++)
        {
            string str2;
            int x;
            cin>>str>>str2>>x;
            addedge(cnt[str],cnt[str2],x);
            addedge(cnt[str2],cnt[str],x);
        }
        cin>>s>>e;
        dij(cnt[s]);
        s.clear();
        e.clear();
        cnt.clear();
    }
    return 0;
}
/*
2 1
a
v
a v 1
a v
3 2
a
b
c
a b 2
b c 3
a c
*/


### 关于约瑟夫环问题的C++实现 #### 问题分析 约瑟夫环是一个经典的算法问题,涉及到循环链表或者数组的操作。给定人数 \( N \) 和淘汰间隔 \( X \),目标是从第一个人开始计数,每次跳过 \( X-1 \) 个人并淘汰下一个人,直到所有人都被淘汰为止。 根据输入输出的要求[^1][^2],可以通过多种方法解决此问题,其中常用的是基于模拟的方法和数学推导优化的方式。 --- #### 方法一:使用队列模拟过程 通过队列来模拟整个淘汰的过程是一种直观且易于理解的方法。以下是具体实现: ```cpp #include <iostream> #include <queue> using namespace std; int main() { int T; // 测试用例数量 cin >> T; while (T--) { int N, X; // N: 总人数, X: 淘汰间隔 cin >> N >> X; queue<int> q; for (int i = 1; i <= N; ++i) { // 初始化队列 q.push(i); } cout << "["; bool first = true; // 控制输出格式 while (!q.empty()) { for (int i = 1; i < X; ++i) { // 跳过前 X-1 个人 int temp = q.front(); q.pop(); q.push(temp); // 将未淘汰的人重新加入队列尾部 } int out = q.front(); // 当前被淘汰的人 q.pop(); if (!first) { cout << ", "; } else { first = false; } cout << out; // 输出当前被淘汰的人编号 } cout << "]" << endl; } return 0; } ``` 上述代码实现了基本的队列操作逻辑,并按照题目中的输入输出要求进行了格式化处理。 --- #### 方法二:利用数学公式优化求解 如果只需要找到后剩下的那个人,则可以直接应用约瑟夫环的数学公式进行快速计算。设函数 \( f(N, M) \) 表示总共有 \( N \) 个人,每隔 \( M \) 个人淘汰一人时终剩下的人的位置索引(从零开始)。递推关系如下: \[ f(1, M) = 0 \\ f(N, M) = (f(N-1, M) + M) \% N \] 下面是对应的 C++ 实现: ```cpp #include <iostream> using namespace std; // 计算约瑟夫环后一个剩余者的索引位置 int josephus(int n, int m) { int res = 0; for (int i = 2; i <= n; ++i) { res = (res + m) % i; } return res; } int main() { int T; // 测试用例数量 cin >> T; while (T--) { int N, X; // N: 总人数, X: 淘汰间隔 cin >> N >> X; int lastPersonIndex = josephus(N, X); // 获取后一个剩余者的位置索引 cout << lastPersonIndex + 1 << endl; // 结果转换为人的真实编号(从1开始) } return 0; } ``` 这种方法的时间复杂度为 \( O(N) \)[^2],适用于较大的数据规模。 --- #### 方法三:直接返回指定结果 某些情况下可能仅需提供特定的结果而无需展示中间步骤。例如,在引用[2]中提到的例子中,已知部分测试用例及其对应答案。这种场景下可采用硬编码方式完成提交任务。然而需要注意实际比赛中应尽量避免此类做法。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值