3种方法解决PAT_1003_最短路径

原题链接:http://www.patest.cn/contests/pat-a-practise/1003

典型的最短路径,也稍微变了下。

Dijkstra算法,麻烦,容易出错。

#include <iostream>
#include <fstream>
#include <algorithm>
#define INT_MAX       2147483647
#define INT_MIN     (-2147483647 - 1)

using namespace std;

int path[500][500];
int d[500];
int exist[500];
int s, e;
int n, m;
int rescue[500];
int cnt[500];
int r[500];

void in()
{
    ifstream cin("in.txt");
    cin >> n >> m >> s >> e;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            path[i][j] = INT_MAX;
        }
    }
    for (int i = 0; i < n; i++)
    {
        cin >> rescue[i];
    }
    for (int i = 0; i < m; i++)
    {
        int a, b;
        cin >> a >> b;
        cin >> path[a][b];
        path[b][a] = path[a][b];
    }
}

int nearest()
{
    int max = INT_MAX;
    int index;
    for (int i = 0; i < n; i++)
    {
        if (!exist[i] && d[i] < max)
        {
            max = d[i];
            index = i;
        }
    }
    return index;
}

void shortest()
{
    exist[s] = 1;
    for (int i = 0; i < n; i++)
    {
        d[i] = path[s][i];
        cnt[i] = (d[i] == INT_MAX) ? 0 : 1;
        r[i] = (d[i] == INT_MAX) ? INT_MIN : rescue[i] + rescue[s];
    }
    r[s] = rescue[s];
    d[s] = 0;
    cnt[s] = 1;
    for (int i = 0; i < n - 1; i++)
    {
        int index = nearest();
        exist[index] = 1;
        for (int j = 0; j < n; j++)
        {
            if (exist[j] || path[index][j] == INT_MAX)
            {
                continue;
            }
            if (d[index] + path[index][j] < d[j])
            {
                d[j] = d[index] + path[index][j];
                cnt[j] = cnt[index];
                r[j] = r[index] + rescue[j];
            }
            else if (d[index] + path[index][j] == d[j])
            {
                cnt[j] += cnt[index];
                r[j] = max(r[index] + rescue[j], r[j]);
            }
        }
    }
    cout << cnt[e] << ' ' << r[e] << endl;
}

int main(int argc, char **argv)
{
    in();
    shortest();
    return 0;
}


dfs深搜,最好的算法,简洁,复杂度高。

#include <iostream>
#include <fstream>

int d[500][500];
int visited[500];
int teams[500];
int n, m;
int s, e;

#define INF 0x7fffffff

int min_dist=INF;
int max_amount;
int cnt;

using namespace std;

void dfs(int start, int dist, int amount)
{


//下面的continue是剪枝
    if (start == e)
    {
        if (dist < min_dist)
        {
            cnt = 1;
            min_dist = dist;
            max_amount = amount;
        }
        else if (dist == min_dist)
        {
            cnt++;
            if (amount>max_amount)
            {
                max_amount = amount;
            }
        }
        return;
    }
    for (int i = 0; i < n; i++)
    {
        if (d[start][i] != 0 && !visited[i])
        {
            visited[i] = 1;
            dfs(i, dist+d[start][i], amount+teams[i]);
            visited[i] = 0;
        }
    }
    
}

int main(int argc, char **argv)
{
    ifstream cin("in.txt");
    cin >> n >> m >> s >> e;
    for (int i = 0; i < n; i++)
    {
        cin >> teams[i];
    }
    for (int i = 0; i < m; i++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        d[a][b] = d[b][a] = c;
    }
    visited[s] = 1;
    dfs(s, 0, teams[s]);
    cout << cnt << ' ' << max_amount << endl;
    return 0;
}


bfs广搜,还行。不算麻烦。

#include <iostream>
#include <fstream>
#include <vector>
#include <cstring>

#define INF 0x7fffffff

using namespace std;

int teams[500];
int dist[500][500];
int n, m;
int s, e;

vector<vector<int> > ve;
int d[500];

int cnt = 0;
int max_amount = 0;
int min_dist = INF;

void bfs(int s, int e)
{
    vector<int> data;
    data.push_back(s);
    data.push_back(0);
    data.push_back(teams[s]);
    ve.push_back(data);
    int i = 0;
    while (i<ve.size())
    {
        data = ve[i++];
        int start, pathdist, amount;
        start = data[0];
        pathdist = data[1];
        amount = data[2];


//下面两处continue是剪枝
        if (start == e)
        {
            if (pathdist < min_dist)
            {
                min_dist = pathdist;
                max_amount = amount;
                cnt = 1;
            }
            else if (pathdist == min_dist)
            {
                cnt++;
                if (amount>max_amount)
                {
                    max_amount = amount;
                }
            }
            continue;
        }

        else if (d[start] > 0 && pathdist > d[start])
        {
            continue;
        }

        d[start] = pathdist;
        for (int i = 0; i < n; i++)
        {
            if (dist[start][i] != 0)
            {
                data.clear();
                data.push_back(i);
                data.push_back(d[start] + dist[start][i]);
                data.push_back(amount + teams[i]);
                ve.push_back(data);
            }
        }
    }
    cout << cnt << ' ' << max_amount << endl;
}
int main(int argc, char **argv)
{
    ifstream cin("in.txt");
    cin >> n >> m >> s >> e;
    for (int i = 0; i < n; i++)
    {
        cin >> teams[i];
    }
    for (int i = 0; i < m; i++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        dist[a][b] = dist[b][a] = c;
    }
    bfs(s, e);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值