51Nod 1459 迷宫游戏

9 篇文章 0 订阅
1 篇文章 0 订阅

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

做法:
一种朴素的想法就是最短路咯,毕竟第一问要求嘛,然后我们发现,这种朴素的想法稍加修改就可一AC呀,其实就是在更新最短路的时候顺便更新积分。

代码如下:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#define N 400000
using namespace std;
struct arr
{
    int t,n,w;
}f[N];
int str[N], ls[N], e, s, t, n, m, d[N], g[N], a[N];
bool v[N];

int read()
{
    int s = 0, p = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9' && ch != '-')   ch = getchar();
    if (ch == '-')  p = -1, ch = getchar();
    while (ch >= '0' && ch <= '9')  s = s * 10 + ch - '0', ch = getchar();
    return s * p;
}

int add(int x, int y, int z)
{
    f[++e].t = y;
    f[e].n = ls[x];
    ls[x] = e;
    f[e].w = z;
}

int spfa()
{
    int head = 0, tail = 1;
    str[1] = s;
    v[s] = 1;
    for (int i = 0; i <= n; i++)
        d[i] = 0x7f7f7f7f;
    d[s] = 0;
    g[s] = a[s];
    while (head < tail)
    {
        head += 1;
        int p = str[head];
        for (int i = ls[p]; i; i = f[i].n)
        {
            if (d[p] + f[i].w < d[f[i].t])
            {
                d[f[i].t] = d[p] + f[i].w;
                g[f[i].t] = g[p] + a[f[i].t];
                if (! v[f[i].t])
                {
                    v[f[i].t] = 1;
                    tail += 1;
                    str[tail] = f[i].t;
                }
            }
            else if (d[p] + f[i].w == d[f[i].t])
            {
                g[f[i].t] = max(g[p] + a[f[i].t], g[f[i].t]);
            }
        }
        v[p] = 0;
    }
}

int main()
{

    n = read(), m = read(), s = read(), t = read();
    int x, y, z;
    for (int i = 0; i <= n - 1; i++)
        a[i] = read();
    for (int i = 1; i <= m; i++)
    {
        x = read();
        y = read();
        z = read();
        add(x, y, z);
        add(y, x, z);
    }
    spfa();
    printf("%d ", d[t]);
    printf("%d", g[t]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值