PAT_A1087
PAT甲级1087.
目录
A1087
题目
样例
输入:
6 7 HZH
ROM 100
PKN 40
GDN 55
PRS 95
BLN 80
ROM GDN 1
BLN ROM 1
HZH PKN 1
PRS ROM 2
BLN HZH 2
PKN GDN 1
HZH PRS 1
输出:
3 3 195 97
HZH->PRS->ROM
思路和坑点
由于,对于最短路径的优化条件比较复杂,还需要统计最短路径条数,因此,使用Dijksatra+dfs的方法得到所求的最短路径,其中Dijkstra算法用于获得多条备选路径,dfs对每一条路径进行遍历,然后根据优化尺度比较最终保留符合条件的路径,并输出。
要点:
其中,需要吧所有的城市结点映射成为0~n-1,其中由于起点城市没有happy值,所以不妨直接令起点映射为0,并且happy值为0,方便之后的统计计算。
AC代码
#include<bits/stdc++.h>
using namespace std;
#define MAXV 205
#define INF 0x3fffffff
int n,k; //图的顶点个数,图的边个数
int cnt=0; //记录路径条数
int totalh=-1; //第二优化尺度(总的happy值)
int happy[MAXV]; //happy映射
int G[MAXV][MAXV]; //图
int dis[MAXV]; //最短距离数组
bool vis[MAXV]={false}; //访问标记
string st,ed="ROM"; //起始和结束
vector<int> path[MAXV]; //多路径记录
vector<int> pathout,temppath; //输出路径和临时路径存放
unordered_map<string,int> mp; //城市的下标映射
unordered_map<int,string> mpi;
void D(); //Dijkstra算法
void DFS(int v);
int main(){
#ifdef ONLINE_JUDGE
#else
freopen("1.txt", "r", stdin);
#endif
fill(G[0],G[0]+MAXV*MAXV,INF);
scanf("%d%d",&n,&k);
cin>>st;
mp[st]=0; //起始点映射为0
mpi[0]=st;
happy[0]=0; //起始点的happy为0
for(int i=1;i<n;i++){ //读入happy并完成坐标映射
string temp;
cin>>temp>>happy[i];
mp[temp]=i;mpi[i]=temp;
}
for(int i=0;i<k;i++){ //读入边
string c1,c2;
int ct1,ct2,c;
cin>>c1>>c2>>c;
ct1=mp[c1];ct2=mp[c2];
G[ct1][ct2]=G[ct2][ct1]=c;
}
int edn=mp[ed]; //终点下标
D();
DFS(edn);
int avh=totalh/(pathout.size()-1);
cout<<cnt<<' '<<dis[edn]<<' '<<totalh<<' '<<avh<<'\n';
for(int i=pathout.size()-1;i>=0;i--){
int k=pathout[i];
if(i!=pathout.size()-1) printf("->");
cout<<mpi[k];
}
return 0;
}
void D(){
fill(dis,dis+MAXV,INF);
dis[0]=0;
for(int i=0;i<n;i++){
int u=-1,MIN=INF;
for(int j=0;j<n;j++){
if(vis[j]==false&&dis[j]<MIN){
u=j;
MIN=dis[j];
}
}
if(u==-1) return;
vis[u]=true;
for(int v=0;v<n;v++){
if(vis[v]==false&&G[u][v]!=INF){
if(dis[u]+G[u][v]<dis[v]){
dis[v]=dis[u]+G[u][v];
path[v].clear();
path[v].push_back(u);
}
else if(dis[u]+G[u][v]==dis[v]){
path[v].push_back(u);
}
}
}
}
}
void DFS(int v){
if(v==0){ //当获得一条路径时
cnt++; //路径计数器加一
temppath.push_back(0);
int value=0; //计算当前获得路径的happy值
for(int i=0;i<temppath.size();i++){
int k=temppath[i];
value+=happy[k];
}
if(value>totalh){ //如果happy更多,则更新
totalh=value;
pathout=temppath;
}
else if(value==totalh&&temppath.size()<pathout.size()){ //如果happy相同,城市个数少的平均happy更高,则更新
pathout=temppath;
}
temppath.pop_back();
return;
}
temppath.push_back(v);
for(int i=0;i<path[v].size();i++){
DFS(path[v][i]);
}
temppath.pop_back();
}