您的位置:首页 > 其它

PAT L2-001 紧急救援

2019-05-02 11:55 36 查看

 

这道题折腾了我好久。。。刚开始想用广度搜索但是感觉特别复杂,后来上网看题解发现一种算法dijkstra,为了看懂别人的题解我又去学习了dijkstra,然后又调试了好久才把路线数目不对、最大救援队数目不对、路线输出不对的问题解决(相当于全做错了)。

题目说明:

作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图。在地图上显示有多个分散的城市和一些连接城市的快速道路。每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上。当其他城市有紧急求助电话给你的时候,你的任务是带领你的救援队尽快赶往事发地,同时,一路上召集尽可能多的救援队。

输入格式:

输入第一行给出4个正整数N、M、S、D,其中N(2≤N≤500)是城市的个数,顺便假设城市的编号为0 ~ (N−1);M是快速道路的条数;S是出发地的城市编号;D是目的地的城市编号。

第二行给出N个正整数,其中第i个数是第i个城市的救援队的数目,数字间以空格分隔。随后的M行中,每行给出一条快速道路的信息,分别是:城市1、城市2、快速道路的长度,中间用空格分开,数字均为整数且不超过500。输入保证救援可行且最优解唯一。

输出格式:

第一行输出最短路径的条数和能够召集的最多的救援队数量。第二行输出从S到D的路径中经过的城市编号。数字间以空格分隔,输出结尾不能有多余空格。

输入样例:

[code]4 5 0 3
20 30 40 10
0 1 1
1 3 2
0 3 3
0 2 2
2 3 2

输出样例:

[code]2 60
0 1 3

个人思路: 

我的思路挺复杂的。我定义了七个数组,具体每个数组的作用我在代码注释了都写明白了。然后先把dijkstra算法写上,随后再依次添加记录每个节点最大救援队数目,记录路线的功能,最后输出。

代码实现:

[code]#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
int mmap[501][501];//两节点之间距离
int dist[501];//到达源点的最短距离
int sum[501];//到达每个节点的数量
int maxn[501];//到达每个节点最大救援队数量
int pre[501];//储存结果路径

int helper[501];//城市中救援队数量
bool vis[501];//是否拜访过该城市
int N, M, S, D, c1, c2, x;
void Dijkstra()
{
memset(sum, 0, sizeof sum);
memset(pre, -1, sizeof pre);
memset(dist, INF, sizeof dist);
int start = S;
vis[start] = 1;
for (int i = 0; i < N; ++i)//先把每个节点救援队数量初始化为当前节点救援队数量
maxn[i] = helper[i];
for (int i = 0; i < N; ++i)
{
dist[i] = mmap[start][i];
if (mmap[start][i] != INF /*&& start != i*/)
{
sum[i] = 1;
if(start!=i)//如果两个结点互通那么当前节点救援队数目应该加上另一个的数目
maxn[i] += maxn[start];
}
}
for (int i = 1; i < N; ++i)
{
int minn = INF;
for (int j = 0; j < N; ++j)
{
if (vis[j] == 0 && minn > dist[j])
{
minn = dist[j];
start = j;
}
}
vis[start] = 1;//刚开始不小心放在里层循环
for (int j = 0; j < N; ++j)
{
//if (!vis[j])//add
//{
if (dist[j] > dist[start] + mmap[start][j])//	刚开始写成了minn>dist[start]+mmap[start][j]
{
pre[j] = start;
dist[j] = dist[start] + mmap[start][j];
sum[j] = sum[start];
maxn[j] = maxn[start] + helper[j];
}
else if (dist[j] == dist[start] + mmap[start][j])
{
if (maxn[j] <= maxn[start] + helper[j]&&j!=start)
{
maxn[j] = maxn[start] + helper[j];
pre[j] = start;
}
if(start!=j)//访问到相同节点不能相加
sum[j] += sum[start];
}
//}
}
}
}
void print()
{
int x=D;
stack<int>sta;
cout << sum[D] << " " << maxn[D] << endl;
while (x !=-1)
{
sta.push(x);
x = pre[x];
}
sta.push(S);
while (sta.size() > 1)
{
cout << sta.top() << " ";
sta.pop();
}
cout << sta.top() << endl;
sta.pop();
}
int main()
{
cin >> N >> M >> S >> D;
memset(mmap, INF, sizeof mmap);
for (int i = 0; i < N; ++i)
cin >> helper[i];
for (int i = 0; i < M; ++i)
{
cin >> c1 >> c2 >> x;
mmap[c1][c2] = mmap[c2][c1] = x;
}
for (int i = 0; i < N; ++i)//这一步不能偷懒放到上一步的循环中
mmap[i][i] = 0;
Dijkstra();
print();
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: