浙江大学2019年机试 7-4 Ambulance Dispatch (30 分)

考察:无向有权图的最短路径;
解决办法:1、节点少情况:直接DFS从呼救点去遍历全图,终结点只进入还有救护车的医院,过程中更新最短路径,救护车数量,经过节点数。
2、节点多情况:采用Dijkstra+DFS,用Dij记录每个医院到每个呼救点的最短路径,pre保存,然后用DFS遍历更新找到对应path.
注意点:途中可以经过医院,节点数大于1000,用dij+DFS;
办法一DFS:

using namespace std;
const int maxn = 1011;
const int INF = 1000000;
int G[maxn][maxn]={0};
int na,ns,m,k;
int mindis=INF,mincount = INF,maxcar = -1;
vector<int> tempPath,path,avinum;
bool vis[maxn] = {false};
void DFS(int quy) {
	vis[quy] = true;
	if(quy > ns && avinum[quy-ns] > 0) {
		tempPath.push_back(quy);
		int sumdis = 0;
		for(int i=0; i< tempPath.size()-1; i++) {
			sumdis += G[tempPath[i]][tempPath[i+1]];
		}
		if(mindis > sumdis) {
			path = tempPath;
			mindis = sumdis;
			maxcar = avinum[quy-ns];
			mincount = tempPath.size();
		}else if(mindis==sumdis && maxcar < avinum[quy-ns]){
				maxcar = avinum[quy-ns];
				mincount = tempPath.size();
				path = tempPath;
		}else if(mindis==sumdis && maxcar == avinum[quy-ns] && tempPath.size() < mincount) {
				mincount = tempPath.size();
				path = tempPath;
		}
		tempPath.pop_back();
	}
	tempPath.push_back(quy);
	for(int i=0; i< maxn; i++) {
		if(vis[i] == false && G[quy][i]!=0) {
			vis[i]=true;
			DFS(i);
			vis[i]=false;
		}
	}
	vis[quy] = false;
	tempPath.pop_back();
}
int main() {
	cin>>ns>>na;
	avinum.resize(na+1);
	for(int i=1; i <= na; i++) cin >> avinum[i];
	cin>>m;
	string v1,v2,str;
	int time,quy;
	for(int i=0; i<m; i++) {
		cin>>v1>>v2>>time;
		int n1 = v1[0]=='A'?stoi(v1.substr(2))+ns:stoi(v1);
		int n2 = v2[0]=='A'?stoi(v2.substr(2))+ns:stoi(v2);
		G[n1][n2] = G[n2][n1] = time;
	}
	cin>>k;
	for(int i=0; i<k; i++) {
		path.clear();
		tempPath.clear();
		maxcar = -1;
		mincount = mindis = INF;
		cin>>quy;
		DFS(quy);
		if(path.size() == 0) cout <<"All Busy"<<endl;
		else {
			avinum[path[path.size()-1]-ns]--;
			for(int j = path.size()-1; j>=0; j--) {
				str = path[j]>ns? ("A-"+ to_string(path[j]-ns)):to_string(path[j]);
				cout<<str;
				if(j!=0) cout<<" ";
			}
			cout<<endl<<mindis<<endl;
		}
	}
	return 0;
}

方法二(dijkstra+DFS):参考20-浙大计算机考研总群241321218 20-云同学代码

#include<bits/stdc++.h>
using namespace std;
const int INF=1000000000;
int weight[15],G[1015][1015],d[15][1015];
vector<int> pre[15][1015],temp,path;
bool inq[1015];
int ns,na,m,k;
void dijkstra(int index){
	 fill(inq,inq+1015,false);
	 fill(d[index],d[index]+1015,INF);
	 d[index][1000+index]=0;
	 for(int i=1;i<=1000+na;i++){
		 int u=-1,MIN=INF;
		 for(int j=1;j<=1000+na;j++){
			 if(inq[j]==false&&d[index][j]<MIN){
				 MIN=d[index][j];
				 u=j;
			 }
		 }
		 if(u==-1) return;
		 inq[u]=true;
		 for(int v=1;v<=1000+na;v++){
			 if(inq[v]==false&&G[u][v]!=INF){
				 if(d[index][u]+G[u][v]<d[index][v]){
					 pre[index][v].clear();
					 pre[index][v].push_back(u);
					 d[index][v]=d[index][u]+G[u][v];
				 }else if(d[index][u]+G[u][v]==d[index][v]) pre[index][v].push_back(u);
			 }
		 }
	 }
}
void dfs(int s,int ed){
	temp.push_back(s);
	if(s==ed+1000){
		if(path.size()==0) path=temp;
		else {
			if(temp.size()<=path.size()) path=temp;
		}
		temp.pop_back();
		return;
	}
	for(int i=0;i<pre[ed][s].size();i++){
		dfs(pre[ed][s][i],ed);
	}
	temp.pop_back();
}

int main(){
#ifdef ONLINE_JUDGE
#else 
	freopen("test.txt","r",stdin);
#endif
	
	scanf("%d%d",&ns,&na);
	for(int i=1;i<=na;i++) scanf("%d",&weight[i]);
	scanf("%d",&m);
	fill(G[0],G[0]+1015*1015,INF);
	for(int i=0;i<m;i++){
		char str[10];
		int u,v;
		scanf("%s",str);
		if(str[0]=='A'){
			sscanf(str,"A-%d",&u);
			u+=1000;
		}else u=stoi(str);
		scanf("%s",str);
		if(str[0]=='A'){
			sscanf(str,"A-%d",&v);
			v+=1000;
		}else v=stoi(str);
		scanf("%d",&G[u][v]);
		G[v][u]=G[u][v];
	}
	for(int i=1;i<=na;i++){
		dijkstra(i);
	}
	scanf("%d",&k);
	for(int i=0;i<k;i++){
		int aim,mindis=INF,maxleft=-1,index;
		vector<int> res;
		scanf("%d",&aim);
		for(int j=1;j<=na;j++){
			if(weight[j]>0){
				if(d[j][aim]<mindis){
					mindis=d[j][aim];
					maxleft=weight[j];
					dfs(aim,j);
					res=path;
					path.clear();
					index=j;
				}else if(d[j][aim]==mindis&&weight[j]>weight[index]){
					dfs(aim,j);
					maxleft=weight[j];
					res=path;
					path.clear();
					index=j;
				}else if(d[j][aim]==mindis&&weight[j]==weight[index]){
					dfs(aim,j);
					if(path.size()<res.size()) res=path,index=j;
					path.clear();
				}
			}
		}
		if(maxleft==-1) printf("All Busy\n");
		else {
			weight[index]--;
			for(int j=res.size()-1;j>=0;j--){
				if(res[j]>1000) printf("A-%d",res[j]-1000);
				else printf("%d",res[j]);
				if(j) printf(" ");
				else printf("\n");
			}
			printf("%d\n",d[index][aim]);
		}
	}
}
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值