PTA7-12 城市间紧急救援 (25 分)
关于这个题呢,我当时也想了很久没有一点头绪。所以,菜鸡的我一如既往的打开了CSDN(手动滑稽)。我看了很多大佬的写法,最普遍的应该就是dijkstra+dp了。于是,在众多大佬的代码熏陶下,我琢磨出了比较简单的写法。也不能说简单,也就是代码可读性高一点而已。小白写文,如有错误还望多多谅解!
输入格式:
输入第一行给出4个正整数N、M、S、D,其中N(2≤N≤500)是城市的个数,顺便假设城市的编号为0 ~ (N−1);M是快速道路的条数;S是出发地的城市编号;D是目的地的城市编号。
第二行给出N个正整数,其中第i个数是第i个城市的救援队的数目,数字间以空格分隔。随后的M行中,每行给出一条快速道路的信息,分别是:城市1、城市2、快速道路的长度,中间用空格分开,数字均为整数且不超过500。输入保证救援可行且最优解唯一。
输出格式:
第一行输出最短路径的条数和能够召集的最多的救援队数量。第二行输出从S到D的路径中经过的城市编号。数字间以空格分隔,输出结尾不能有多余空格。
输入样例:
4 5 0 3
20 30 40 10
0 1 1
1 3 2
0 3 3
0 2 2
2 3 2
输出样例:
2 60
0 1 3
我就用注释来解释吧
//dijstra+dp
#include "bits/stdc++.h"
using namespace std;
int ma[501][501],peo[501],Count[501],vis[501],path[501],dist[501],ph[501];
//ma[501][501]表示地图,peo[501]表示拉的人数,Count[501]表示路的条数
//vis[501]标记点,path[501]记录路径,dist[501]最短距离,ph[501]每个城市的人数
int n,m,s,d;
void ath(int d)//打印路径
{
if(path[d]!=-1)
{
ath(path[d]);
cout<<path[d]<<' ';
}
}
int main()
{
cin>>n>>m>>s>>d;
memset(ma,0x3f,sizeof(ma));//图max
memset(dist,0x3f,sizeof(dist));//点距max
memset(path,-1,sizeof(path));//记录路径
memset(Count,1,sizeof(Count));//道路条数
for(int i=0;i<n;i++) cin>>ph[i];
//初始化...
dist[s]=0;
Count[s]=1;
//vis[s]=1;
peo[s]=ph[s];
while(m--)//把路存到地图上
{
int j,k,l;
cin>>j>>k>>l;
ma[j][k]=ma[k][j]=l;
}
//接下来就是重头戏dijstra了
for(int i=0;i<n;i++)
{
int t=-1;
for(int j=0;j<n;j++)//找距离最短的点
{
if((t==-1||dist[j]<dist[t])&&!vis[j]) t=j;
}
if(t==-1) break;//所有点都找过了
vis[t]=1;//标记该点
for(int j=0;j<n;j++)
{
if(dist[t]+ma[t][j]<dist[j])//如果路径更短的话(又名松弛)
{
dist[j]=dist[t]+ma[t][j];//更新距离
path[j]=t;//记录路径
Count[j]=Count[t];//记录路数
peo[j]=ph[j]+peo[t];//记录总人数
}
else if(dist[t]+ma[t][j]==dist[j])//如果一样长
{
Count[j]+=Count[t];//路数就要增加
if(peo[t]+ph[j]>peo[j])//如果人数更多
{
peo[j]=peo[t]+ph[j];//拉人
path[j]=t;//记录路径
}
}
}
}
cout<<Count[d]<<' '<<peo[d]<<endl;
ath(d);
cout<<d;
}
就这样王子和公主过上了幸福快乐的生活 我们就成功解决了这个题!
cheer!