2019浙江大学考研复试上机题 Ambulance Dispatch (30 分) ---测试点4

总体的解题思路:

利用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 Busy\n");
		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("%d\n",minTime);
		}
	}
}

值得注意的是47行中的判断语句是小于号。如果提交这段代码是无法通过最后一个测试点的。

如果想要通过最后一个测试点,只要把47行处判断语句的小于号改成小于等于号即可。

因此我怀疑有可能是最后一个测试点出现了这样的数据,即从一个呼叫求助点到某个救护中心center有两条路,这两条路经过的街道数一样,路径的时间是一样的,而且最终该救护中心是符合题目要求的,从而出现了问题,如果加上等于号就取最后一条路径输出从而正好跟答案的数据一致。

我在dfs的过程中加入一个小判断,即如果出现两条街道路径时间是一样的且经过的街道数是一样那么就让程序进入死循环。经过测试,我发现数据中确实存在从一个呼叫求助点到某个救护中心存在两条以上时间相同且经过街道数一样的路径。

以上都是我的分析和猜测,这个题我去年8月份第一次做就没想通,然后查了网上的资料发现大家基本都跟我存在同样的疑惑,然后就想着过段时间再看看网上有没有资料,结果半年后来看关于这个题的解析还是很少。因此,写下这篇文章希望有老师、同学能不吝赐教,不胜感激。

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值