直捣黄龙 【学习进度条6】

L3:直捣黄龙

【题目】

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

【代码解释】

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

【可粘贴代码】

有略微改动

#include<bits/stdc++.h>
using namespace std;
const int N=210;

int scnt[N];//到每个城镇的最短路数量
int node[N];//到每个城镇最短路的结点个数 
int e[N][N];//城镇道路
int csnum[N];//城镇敌军数量
int enm[N];//到每个城镇最短路经过的最多敌人 
map<string,int> mp;//城镇名字对应编号 
string city[N];//城镇名字 
string s,t;//己方和敌方
int ss,tt;
int n,k; 

void dijskra(int cost[],int pre[]){
//优先级:最短路-->最多结点-->最多敌军数 
	int flag[n+1];
	flag[ss]=1;
	for(int i=1;i<n;i++){
		cost[i]=e[ss][i];
		flag[i]=0;
		pre[i]=ss;
	}//初始化
	for(int j=1;j<n;j++){
		//循环n-1次
		int min=INT_MAX; 
		int minj=ss;
		for(int i=1;i<n;i++){
			if(flag[i]==0&&min>cost[i]&&cost[i]!=INT_MAX){
				min=cost[i];
				minj=i;
			}
		}//找最小
		flag[minj]=1;
		for(int i=1;i<n;i++){
			if(flag[i]==0){
				if(cost[i] > cost[minj]+e[minj][i]&&e[minj][i]!=INT_MAX){
					pre[i]=minj;
					cost[i]=cost[minj]+e[minj][i];
					scnt[i]=scnt[minj];//最短路替换 
					node[i]=node[minj]+1;
					enm[i]=enm[minj]+csnum[i];
				}else if(cost[i]==cost[minj]+e[minj][i]&&e[minj][i]!=INT_MAX){
					scnt[i]+=scnt[minj];//最短路增加  
					if(node[i]<node[minj]+1){
					//经过minj路段 结点最多
						pre[i]=minj;
						node[i]=node[minj]+1; 
						enm[i]=enm[minj]+csnum[i];
					}else if(node[i]==node[minj]+1){
					//最多结点数相同,找敌人最多数
						if(enm[i]<enm[minj]+csnum[i]){
							pre[i]=minj;
							enm[i]=enm[minj]+csnum[i];
						} 
					}
				}
			}
		} //更新  
	}
}

int main(){
	scanf("%d%d",&n,&k);
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			e[i][j]=INT_MAX; 
		}
	} 
	cin>>s>>t;
	city[0]=s;
	mp[s]=0;
	csnum[0]=0;
	for(int i=1;i<n;i++){
		cin>>city[i];
		int num;
		scanf("%d",&num);
		mp[city[i]]=i;
		csnum[i]=num;
		enm[i]=num;
	}
	getchar();
	for(int i=0;i<k;i++){
		string u,v;
		cin>>u>>v;
		int len;
		scanf("%d",&len);
		int a=mp[u];
		int b=mp[v];
		e[a][b]=len;
		e[b][a]=len;//保存路径
	} 
	int ss=mp[s];//起点 
	int tt=mp[t];//终点
	for(int i=1;i<n;i++){
		if(e[ss][i]!=INT_MAX){
			scnt[i]=1;
			node[i]=2;
		}
		else{
			scnt[i]=0;
			node[i]=1;
		}
	} 
	int cost[n+1];
	int pre[n+1];
	dijskra(cost,pre);
	/*for(int i=1;i<n;i++){
		cout<<cost[i]<<" "<<pre[i]<<endl;
	}*/
	stack<string> st;
	int i=tt;
	for(;i!=ss;i=pre[i]){
		st.push(city[i]);
	}
	cout<<s<<"->";
	while(st.size()>1){
		string p=st.top();
		st.pop();
		cout<<p<<"->";
	}
	string p=st.top();
	st.pop();
	cout<<p<<endl;
	cout<<scnt[tt]<<" "<<cost[tt]<<" "<<enm[tt];
	return 0;
}

代码中起的名字不太恰当可能会造成代码可读性不好,下面两篇感觉还不错,推荐给大家:

  1. 相同dijkstra变形的思路的:
    https://www.cnblogs.com/hulian425/p/14049914.html
  2. 不同思路——深度优先搜索的:
    https://blog.csdn.net/tobealistenner/article/details/88685014

这个题和城市间紧急救援有些类似,可以参考着来看。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值