Dijkstra算法初步 - 迷宫问题

你来到一个迷宫前。该迷宫由若干个房间组成,每个房间都有一个得分,第一次进入这个房间,你就可以得到这个分数。还有若干双向道路连结这些房间,你沿着这些道路从一个房间走到另外一个房间需要一些时间。游戏规定了你的起点和终点房间,你首要目标是从起点尽快到达终点,在满足首要目标的前提下,使得你的得分总和尽可能大。现在问题来了,给定房间、道路、分数、起点和终点等全部信息,你能计算在尽快离开迷宫的前提下,你的最大得分是多少么?

Input

第一行4个整数n (<=500), m, start, end。n表示房间的个数,房间编号从0到(n - 1),m表示道路数,任意两个房间之间最多只有一条道路,start和end表示起点和终点房间的编号。
第二行包含n个空格分隔的正整数(不超过600),表示进入每个房间你的得分。
再接下来m行,每行3个空格分隔的整数x, y, z (0<z<=200)表示道路,表示从房间x到房间y(双向)的道路,注意,最多只有一条道路连结两个房间, 你需要的时间为z。
输入保证从start到end至少有一条路径。

Output

一行,两个空格分隔的整数,第一个表示你最少需要的时间,第二个表示你在最少时间前提下可以获得的最大得分。

Input示例

3 2 0 2
1 2 3
0 1 10
1 2 11

Output示例

21 6

---------------------------------------------------我是分割线^_^-------------------------------------------------

此题为迪杰斯特拉算法的基础题,用来了解单源最短路径的求法,其实一开始的入门都是在《啊哈!算法》这本书中看到的,最短路径问题,这个题可以使用邻接表和优先队列做,但我都没用,我用了效率比较低下的二维数组,不过也有被难倒的地方,就是在计算最大分数的时候,被卡了有几个小时都找不到错误后来发现原来是因为相等的情况多余了,要注意最小最大和最长最短的一些限制条件,以后写的时候要提醒自己注意= =。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;

#define Int __int64
#define INF 0x3f3f3f3f

const int MAXN = 555;
int n, m, s, e;

int maze[MAXN][MAXN];
int dis[MAXN];
bool vis[MAXN];
int score[MAXN];
int ans[MAXN];

void init() {
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            if (i == j) maze[i][j]  = 0;
            else maze[i][j] = INF;
        }
    }
    memset(dis, 0, sizeof(dis));
    memset(vis, false, sizeof(vis));
    memset(ans, false, sizeof(ans));
}

void Dijkstra() {
    for (int i = 0; i < n; i++) {
        scanf("%d", &score[i]);
    }

    int u, v, w;
    for (int i = 0; i < m; i++) {
        scanf("%d %d %d", &u, &v, &w);
        if (w < maze[u][v]) {
            maze[u][v] = w;
            maze[v][u] = w;
        }
    }

    for (int i = 0; i < n; i++) {
        dis[i] = maze[s][i];
        if (i != s) ans[i] = score[s] + score[i];//初始化的时候也要判断等于的情况
        else ans[i] = score[i];
    }

    for (int i = 0; i < n; i++) {

        int pos, Min = INF;
        for (int a = 0; a < n; a++) {
            if (vis[a]) continue;
            if (dis[a] < Min) {
                Min = dis[a];
                pos = a;
            }
        }
        vis[pos] = true;

        for (int a = 0; a < n; a++) {

            if (maze[pos][a] < INF) {
                if (dis[a] > dis[pos] + maze[pos][a]) {
                    dis[a] = dis[pos] + maze[pos][a];
                    ans[a] = ans[pos] + score[a];
                } else if ((dis[a] == dis[pos] + maze[pos][a]) && (ans[a] < ans[pos] + score[a]) && pos != a) {/*就是这里要判断等于的时候是不行的*/
                    ans[a] = ans[pos] + score[a];
                } else {
                    continue;
                }
            }
        }
    }
}
int main()
{
    freopen("input.txt", "r", stdin);

    while (scanf("%d %d %d %d", &n, &m, &s, &e) != EOF) {
        init();
        Dijkstra();
        printf("%d %d\n", dis[e], ans[e]);
    }
    return 0;
}
 
时间: 2024-08-13 01:08:59

Dijkstra算法初步 - 迷宫问题的相关文章

51nod-迷宫问题(Dijkstra算法)

Dijkstra算法 你来到一个迷宫前.该迷宫由若干个房间组成,每个房间都有一个得分,第一次进入这个房间,你就可以得到这个分数.还有若干双向道路连结这些房间,你沿着这些道路从一个房间走到另外一个房间需要一些时间.游戏规定了你的起点和终点房间,你首要目标是从起点尽快到达终点,在满足首要目标的前提下,使得你的得分总和尽可能大.现在问题来了,给定房间.道路.分数.起点和终点等全部信息,你能计算在尽快离开迷宫的前提下,你的最大得分是多少么? Dijkstra算法是一个经典的算法--他是荷兰计算机科学家D

Dijkstra算法 小白说明

Dijkstra算法 小白说明 Dijkstra算法,书上其实说的很简洁,仔细看,仔细思考是会理解的. 如果不限制篇幅,当然可以更细致一些,那么自己按照理解,试着慢慢讲下. 一,问题: 从某个源点,到其他各点的最短路径. 注意,不要想成某一个点,到某个点的最短路径.这样的话思路不是一样的. 二,分析. 先抛弃书中所有关于最短路径的引理,定理,公理.... 先看图. 要找到从0点.到所有点的最短路径. 假如,小明,站在0点.他很渴,天气很热,再不喝水要渴死,而每个其他点,都有一瓶水,点和点之间的交

Dijkstra算法详细(单源最短路径算法)

介绍 对于dijkstra算法,很多人可能感觉熟悉而又陌生,可能大部分人比较了解bfs和dfs,而对dijkstra和floyd算法可能知道大概是图论中的某个算法,但是可能不清楚其中的作用和原理,又或许,你曾经感觉它很难,那么,这个时候正适合你重新认识它. Dijkstra能是干啥的? Dijkstra是用来求单源最短路径的 就拿上图来说,假如直到的路径和长度已知,那么可以使用dijkstra算法计算南京到图中所有节点的最短距离. 单源什么意思? 从一个顶点出发,Dijkstra算法只能求一个顶

畅通project续HDU杭电1874【dijkstra算法 || SPFA】

http://acm.hdu.edu.cn/showproblem.php?pid=1874 Problem Description 某省自从实行了非常多年的畅通project计划后.最终修建了非常多路.只是路多了也不好,每次要从一个城镇到还有一个城镇时,都有很多种道路方案能够选择,而某些方案要比还有一些方案行走的距离要短非常多.这让行人非常困扰. 如今,已知起点和终点,请你计算出要从起点到终点.最短须要行走多少距离. Input 本题目包括多组数据.请处理到文件结束. 每组数据第一行包括两个正

ACM: HDU 2544 最短路-Dijkstra算法

HDU 2544最短路 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Description 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗? Input 输入包括多组数据.每组数据第一行是两个整数N.M(N<=100,M<

ACM: HDU 3790 最短路径问题-Dijkstra算法

HDU 3790 最短路径问题 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Description 给你n个点,m条无向边,每条边都有长度d和花费p,给你起点s终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的. Input 输入n,m,点的编号是1~n,然后是m行,每行4个数 a,b,d,p,表示a和b之间有一条边,且其长度为d,花费为p.最后一行是

邻接表实现Dijkstra算法以及DFS与BFS算法

//============================================================================ // Name : ListDijkstra.cpp // Author : fffff // Version : // Copyright : Your copyright notice // Description : Hello World in C++, Ansi-style //==========================

Dijkstra算法(求解单源最短路)详解 + 变形 之 poj 1860 Currency Exchange

/* 求解单源最短路问题:Dijkstra算法(该图所有边的权值非负) 关键(贪心): (1)找到最短距离已经确定的节点,从它出发更新与其相邻节点的最短距离: (2)此后不再关心(1)中“最短距离已经确定的节点”. 时间复杂度(大概的分析,不准确): “找到最短距离已经确定的节点” => O(|V|) "从它出发更新与其相邻节点的最短距离" => 邻接矩阵:O(|V|),邻接表:O(|E|) 需要循环以上两个步骤V次,所以时间复杂度:O(V^2) 即:在|E|较小的情况下,

Dijkstra 算法

最短路径算法的基础知识,参见 http://blog.csdn.net/pacosonswjtu/article/details/49894021 Dijkstra算法 涉及到的 优先队列的操作实现(该优先队列的数据类型不是 int , 而是 Distance),详情参见http://blog.csdn.net/pacosonswjtu/article/details/49923389 [1]Dijkstra 算法相关 1.1)贪婪算法一般分阶段去求解一个问题, 在每个阶段它都把当前出现的当做是