1087. All Roads Lead to Rome (30) PAT

最短路径和dfs,先用dijkstra找出最短路径,然后用深搜找出相同路径的数量以及最佳答案;可以用map来标注city

变量设的略乱,囧!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<vector>
using namespace std;
int N,K;
map<string,int>m;//标记城市名字
map<int,string>mm;
int G[205][205];
int h[205],vis[205],dis[205];//每个城市的happyness,标记数组,最短路径标记数组
int route,num_route,avg_h=999999,happy;//最短路径,最短路径的数量,平均happyness,最终路径的happyness
vector<int>res,ans;//保存经过的城市
void dij(){
	vis[0]=1;
	for(int i=0;i<N;i++){
		if(G[0][i]!=0){
			dis[i]=G[0][i];
		}
	}
	for(int i=1;i<N;i++){
		int minn=999999;
		int s;
		for(int i=0;i<N;i++){
			if(minn>dis[i]&&vis[i]==0){
				minn=dis[i];
				s=i;
			}
		}
		vis[s]=1;
		for(int i=0;i<N;i++){
			if(dis[i]>dis[s]+G[s][i]&&G[s][i]!=0){
				dis[i]=dis[s]+G[s][i];
			}
		}
	}
	return ;
}

void dfs(int rou,int route,int end,int s,int num,int ha){
	if(rou>route){
		return ;
	}
	if(s==end){
		if(rou!=route){
			return ;
		}
		num_route++;
		double tmp=ha/num;
		if(ha>happy){
			happy=ha;
			ans=res;
			avg_h=tmp;
		}
		else if(ha==happy){
			if(avg_h<tmp){
				avg_h=tmp;
				ans=res;
				happy=ha;
			}
		}
	}
	for(int i=0;i<N;i++){
		if(vis[i]==0&&G[s][i]!=0){
			vis[i]=1;
			res.push_back(i);
			dfs(G[s][i]+rou,route,end,i,num+1,ha+h[i]);
			res.pop_back();
			vis[i]=0;
		}
	}
}

int main(){
	scanf("%d%d",&N,&K);
	string city,city1,city2;
	int e;
	int cost,hap;
	memset(G,0,sizeof(G));
	memset(h,0,sizeof(h));
	cin>>city;
	m[city]=0;
	mm[0]=city;
	for(int i=1;i<=N-1;i++){
		cin>>city>>hap;
		m[city]=i;
		mm[i]=city;
		if(city=="ROM"){
			e=i;
		}
		h[i]=hap;
	}
	for(int i=0;i<K;i++){
		cin>>city1>>city2>>cost;
		G[m[city1]][m[city2]]=G[m[city2]][m[city1]]=cost;
	}
	memset(vis,0,sizeof(vis));
	memset(dis,999999,sizeof(dis));
	dij();
	route=dis[e];
	memset(vis,0,sizeof(vis));
	dfs(0,route,e,0,0,0);
	printf("%d %d %d %d\n",num_route,route,happy,avg_h);
	cout<<mm[0];
	for(int i=0;i<ans.size();i++){
		cout<<"->"<<mm[ans[i]];
	}
	cout<<endl;
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值