概述
总体的解题思路:
利用Dijkstra算法计算Na个救护中心与其余顶点的最短路径(时间上最短),并且保存救护中心和顶点之间的路径,若有多条也全部保存下来。
当某个顶点v发出救护请求时,对于某个救护中心center,找出顶点v到center的经过街道数最少的路径。然后比较Na个救护中心中符合题意的那个救护中心(若有时间最小就就找时间最小,若时间相等就找车辆更多的救护中心,若时间都是最小且救护车数量都一样就找经过街道数最少的救护中心),当然只考虑还有救护车的救护中心。
按照这个思路(Dijkstra+DFS)可以写出代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1015;
const int inf = 1000000000;
int Ns,Na,M,K;
int G[maxn][maxn];
int ambulance[15];
bool vis[maxn]={false};
int d[15][maxn];
vector<int> pre[15][maxn];
void Dijkstra(int s)
{
fill(vis,vis+maxn,false);
fill(d[s],d[s]+maxn,inf);
d[s][s+Ns]=0;
while(true){
int u=-1, Min=inf;
for(int i=1; i<=Ns+Na; i++){
if(vis[i]==false&&d[s][i]<Min){
Min = d[s][i];
u = i;
}
}
if(u==-1) break;
vis[u]=true;
for(int v=1; v<=Ns+Na; v++){
if(G[u][v]!=inf&&vis[v]==false){
if(d[s][u]+G[u][v]<d[s][v]){
d[s][v]=d[s][u]+G[u][v];
pre[s][v].clear();
pre[s][v].push_back(u);
}
else if(d[s][u]+G[u][v]==d[s][v]){
pre[s][v].push_back(u);
}
}
}
}
}
vector<int> tmpPath,path;
int minS = inf;
int test=0;
void dfs(int now,int ed,int center)
{
if(now==ed){
tmpPath.push_back(now);
if(tmpPath.size()<minS){//注意此时是小于号
path = tmpPath;
minS = path.size();
}
tmpPath.pop_back();
return;
}
tmpPath.push_back(now);
for(int i=0; i<pre[center][now].size(); i++){
dfs(pre[center][now][i],ed,center);
}
tmpPath.pop_back();
}
int main()
{
fill(G[0],G[0]+maxn*maxn,inf);
scanf("%d%d",&Ns,&Na);
for(int i=1; i<=Na; i++){
scanf("%d",&ambulance[i]);getchar();
}
scanf("%d",&M);
char s1[10],s2[10];
int time,u,v,spot;
for(int i=0; i<M; i++){
scanf("%s %s %d",s1,s2,&time);getchar();
if(s1[0]=='A'){
sscanf(s1,"A-%d",&u);
u+=Ns;
}
else u = stoi(s1);
if(s2[0]=='A'){
sscanf(s2,"A-%d",&v);
v+=Ns;
}
else v = stoi(s2);
G[u][v]=G[v][u]=time;
}
for(int s=1; s<=Na; s++){
Dijkstra(s);
}
scanf("%d",&K);
for(int i=0; i<K; i++){
scanf("%d",&spot);
vector<int> ans;
int minTime=inf,maxCars=-1,minStreets=inf,index=-1;
for(int center=Ns+1; center<=Ns+Na; center++){
tmpPath.clear();
path.clear();
minS = inf;
dfs(spot,center,center-Ns);
if(ambulance[center-Ns]>0){
if(d[center-Ns][spot]<minTime){
minTime = d[center-Ns][spot];
maxCars = ambulance[center-Ns];
minStreets = path.size();
ans = path;
index = center-Ns;
}
else if(d[center-Ns][spot]==minTime&&ambulance[center-Ns]>maxCars){
maxCars = ambulance[center-Ns];
minStreets = path.size();
ans = path;
index = center-Ns;
}
else if(d[center-Ns][spot]==minTime&&ambulance[center-Ns]==maxCars&&
path.size()<minStreets){
minStreets = path.size();
ans = path;
index = center-Ns;
}
}
}
if(index==-1) printf("All Busyn");
else{
ambulance[index]--;
for(int z=ans.size()-1; z>=0; z--){
if(ans[z]>Ns) printf("A-%d",ans[z]-Ns);
else printf("%d",ans[z]);
if(z!=0) printf(" ");
else printf("n");
}
printf("%dn",minTime);
}
}
}
值得注意的是47行中的判断语句是小于号。如果提交这段代码是无法通过最后一个测试点的。
如果想要通过最后一个测试点,只要把47行处判断语句的小于号改成小于等于号即可。
因此我怀疑有可能是最后一个测试点出现了这样的数据,即从一个呼叫求助点到某个救护中心center有两条路,这两条路经过的街道数一样,路径的时间是一样的,而且最终该救护中心是符合题目要求的,从而出现了问题,如果加上等于号就取最后一条路径输出从而正好跟答案的数据一致。
我在dfs的过程中加入一个小判断,即如果出现两条街道路径时间是一样的且经过的街道数是一样那么就让程序进入死循环。经过测试,我发现数据中确实存在从一个呼叫求助点到某个救护中心存在两条以上时间相同且经过街道数一样的路径。
以上都是我的分析和猜测,这个题我去年8月份第一次做就没想通,然后查了网上的资料发现大家基本都跟我存在同样的疑惑,然后就想着过段时间再看看网上有没有资料,结果半年后来看关于这个题的解析还是很少。因此,写下这篇文章希望有老师、同学能不吝赐教,不胜感激。
最后
以上就是花痴香菇为你收集整理的2019浙江大学考研复试上机题 Ambulance Dispatch (30 分) ---测试点4的全部内容,希望文章能够帮你解决2019浙江大学考研复试上机题 Ambulance Dispatch (30 分) ---测试点4所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复