|Dijkstra + 多重条件判断(点权)+map映射+dfs打印路径|L3-011 直捣黄龙

78 篇文章 7 订阅
64 篇文章 1 订阅

refer
在这里插入图片描述题意:
找到己方大本营到敌方大本营的一条最短路径,
当这样的路径有多条时选择解放最多城镇的路径 (就是经过的城市越多越好),
当这样的路径也有多条时选择杀敌数最多的路

方法:Dijkstra (模板)+ 多重条件判断。

数据处理:
用map容器对表示城市的字符串做数据映射,
使得城市可以用0到N-1表示,方便建立邻接矩阵,
然后套上最短路径模板 + 三个条件判断。

题目要求求己方大本营PAT到达敌方大本营DBY的最短路径且满足3个条件。

根据图中可知,最短路径为30,且这样的路径有3条:(第一个条件)

1.PAT -> ATP -> DBY
2.PAT -> PMS -> TAP -> DBY
3.PAT -> PTA -> PDS -> DBY

这时候就要考虑第二个条件,沿途解放城市最多的路径(经过城市数最多),通过这个条件可以排除第一条路径,还剩两条。(第二个条件)

2.PAT -> PMS -> TAP -> DBY
3.PAT -> PTA -> PDS -> DBY

这时要考虑第三个条件,杀敌数最多的路径(累加经过城市的士兵),根据图中信息可知,第二条路径的杀敌数为190,第三条路径的杀敌数为210。所以选择第三条路径。(第三个条件)

3.PAT -> PTA -> PDS -> DBY

所以输出结果为:

PAT -> PTA -> PDS -> DBY 3 30 210

	M[s1] = 0;
	MM[0] = s1;//PAT
	for (int i = 1; i < n; i++) {注意啊//点权--敌人数
		string town;
		int Enum;
		cin >> town >> Enum;
		M[town] = i;
		MM[i] = town;//便于路径的打印
		EN[i] = Enum;
	}	
	Dijkstra(M["PAT"]);
	//Dijckstra+点权-----杀敌数&解放城市数---最短路径条数
	void Dijkstra(int s) {
		fill(d, d + N, INF);
		memset(kill, 0, sizeof(kill));
		memset(city, 0, sizeof(city));
		memset(num, 0, sizeof(num));
	
		d[s] = 0;
		kill[s] = 0;
		city[s] = 0;
		num[s] = 1;	
		
		for (int i = 0; i < n; i++) {//[0,n-1]
			int MIN = INF, u = -1;
			for (int j = 0; j < n; j++) {
			//求最小值
				if (vis[j] == false && d[j] < MIN) {
					MIN = d[j];
					u = j;
			}
		}
		if (u == -1)return;
		vis[u] = true;
		for (int v = 0; v < n; v++) {
			if (vis[v] == false && G[u][v] != INF) {
				if (d[u] + G[u][v] < d[v]) {
					d[v] = d[u] + G[u][v];
					kill[v] = kill[u] + EN[v];
					city[v] = city[u] + 1;
					pre[v] = u;
					num[v] = num[u];
				}
				else if (d[u] + G[u][v] == d[v]) {
					if (city[u] + 1 > city[v]){
						city[v]=city[u] + 1;
						kill[v] = kill[u] + EN[v];
						pre[v] = u;
					}
					else if (city[u] + 1 == city[v]) {
						if (kill[u] + EN[v] > kill[v]) {
							kill[v] = kill[u] + EN[v];
							pre[v] = u;
							}
					}
					num[v] += num[u];
				}
			}
		}
	}
}

void dfs(int v) {
	if (v == M[s1]) {
		cout << MM[v];
		return;
	}
	dfs(pre[v]);
	cout << "->" << MM[v];
}
//合适的路径,最快的速度
//这样的路径不唯一,有效杀伤最多敌军的路径

//输入
//10 12 PAT DBY------N(城镇总数) K(城镇间道路道路的长度) 己方大本营代号 敌方大本营代号
//随后N-1行,(除了己方大本营外)的一个城镇的代号 驻守的敌军数量
//DBY 100
//PTA 20
//PDS 90
//PMS 40
//TAP 50
//ATP 200
//LNN 80
//LAO 30
//LON 70
//随后K行
//城镇1 城镇2 距离
//PAT PTA 10
//PAT PMS 10
//PAT ATP 20
//PAT LNN 10
//LNN LAO 10
//LAO LON 10
//LON DBY 10
//PMS TAP 10
//TAP DBY 10
//DBY PDS 10
//PDS PTA 10
//DBY ATP 10

//输出:
//速度最快、解放最多、杀伤最强的路径
//己方大本营->城镇1->...->敌方大本营
//最快进攻路劲的条数、最短进攻距离、歼敌总数
//PAT->PTA->PDS->DBY
//3 30 210

#include <iostream>
#include <map>
#include <cstring>
using namespace std;
const int N = 1000;
const int INF = 1000000000;

map<string,int> M;
map<int, string>MM;
int n, m;
string s1, s2;
int G[N][N];
int EN[N] = {0};
int d[N];
int vis[N] = { false };
int minD = INF;
int kill[N],city[N],num[N];
int pre[N] = { 0 };
int minD_num = 0;

void dfs(int v) {
	if (v == M[s1]) {
		cout << MM[v];
		return;
	}
	dfs(pre[v]);
	cout << "->" << MM[v];
}

void Dijkstra(int s) {
	fill(d, d + N, INF);
	memset(kill, 0, sizeof(kill));
	memset(city, 0, sizeof(city));
	memset(num, 0, sizeof(num));
	d[s] = 0;
	kill[s] = 0;
	city[s] = 0;
	num[s] = 1;

	for (int i = 0; i < n; i++) {
		int MIN = INF, u = -1;
		for (int j = 0; j < n; j++) {
			if (vis[j] == false && d[j] < MIN) {
				MIN = d[j];
				u = j;
			}
		}
		if (u == -1)return;
		vis[u] = true;
		for (int v = 0; v < n; v++) {
			if (vis[v] == false && G[u][v] != INF) {
				if (d[u] + G[u][v] < d[v]) {
					d[v] = d[u] + G[u][v];
					kill[v] = kill[u] + EN[v];
					city[v] = city[u] + 1;
					pre[v] = u;
					num[v] = num[u];
				}
				else if (d[u] + G[u][v] == d[v]) {
					if (city[u] + 1 > city[v]){
						city[v]=city[u] + 1;
						kill[v] = kill[u] + EN[v];
						pre[v] = u;
					}
					else if (city[u] + 1 == city[v]) {
						if (kill[u] + EN[v] > kill[v]) {
							kill[v] = kill[u] + EN[v];
							pre[v] = u;
						}
					}
					num[v] += num[u];
				}
			}
		}
	}
}


int main() {
	cin >> n >> m >> s1 >> s2;
	fill(G[0], G[0] + N * N, INF);
	M[s1] = 0;
	MM[0] = s1;
	for (int i = 1; i < n; i++) {注意啊
		string town;
		int Enum;
		cin >> town >> Enum;
		M[town] = i;
		MM[i] = town;
		EN[i] = Enum;
	}
	for (int i = 0; i < m; i++) {
		string town1, town2;
		int dist;
		cin >> town1 >> town2 >> dist;
		G[M[town1]][M[town2]] = G[M[town2]][M[town1]] = dist;
	}
	Dijkstra(M["PAT"]);
	dfs(M[s2]);
	cout << endl;
	cout << num[M[s2]] << " " << d[M[s2]] << " " << kill[M[s2]];

}

/*
10 12 PAT DBY
DBY 100
PTA 20
PDS 90
PMS 40
TAP 50
ATP 200
LNN 80
LAO 30
LON 70
PAT PTA 10
PAT PMS 10
PAT ATP 20
PAT LNN 10
LNN LAO 10
LAO LON 10
LON DBY 10
PMS TAP 10
TAP DBY 10
DBY PDS 10
PDS PTA 10
DBY ATP 10
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值