1087 All Roads Lead to Rome (30 分)

题意:输入城市个数、路线个数、出发城市。城市的快乐值(权重),城市之间的路线花费(权重),求最短路线个数、最短路线花费,沿途城市快乐值之和、平均快乐值题目链接

思路:

原本想将城市名hash之后变量、发现数据范围过大、通过map实现城市下标以及下标与城市之间的映射、通过dijkstra算法,再通过dfs获取所求

#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
#include<iostream>
#define INF 100000
const int M=210;
using namespace std;
map<string,int> strtoint;
map<int,string> inttostr;
char start[5];
int Happy[M]={0},G[M][M],dis[M],order=0,Start,ROM;
bool visit[M]={false};
vector<int> pre[M];
int Code(string a){
	if(strtoint.find(a)==strtoint.end())
	{
		strtoint[a]=order;
		inttostr[order]=a;
		return order++;
	}else return strtoint[a];
}
void dijk(int v,int n)
{
	fill(dis,dis+M,INF);
	dis[v]=0;
	for(int i=0;i<n;i++)
	{
		int u=-1,Min=INF;
		for(int j=0;j<n;j++)
		{
			if(!visit[j]&&dis[j]<Min){
				Min=dis[j];
				u=j;
			}
		}
		if(u==-1) return;
		visit[u]=true;
		for(int w=0;w<n;w++)
		{
			if(!visit[w]&&G[u][w]!=INF)
			{
				if(dis[u]+G[u][w]<dis[w]){
					dis[w]=dis[u]+G[u][w];
					pre[w].clear();
					pre[w].push_back(u);  //可能有多个前缀点
				}else if(dis[u]+G[u][w]==dis[w]){
					pre[w].push_back(u);
				}
			}
		}
	} 
}
int leastcost=INF,maxHappy=-1,num=0;
double maxAvg;
vector<int> ans,tmp;
void dfs(int v,int n,int cost,int sumHappy)
{	
	tmp.push_back(v);
	if(v==Start)
	{
		if(cost<leastcost)
		{
			leastcost=cost;
			num=1;
			maxHappy=sumHappy;
			maxAvg=1.0*sumHappy/n;
			ans=tmp;
		}else if(cost==leastcost){
			if(sumHappy>maxHappy){
				maxHappy=sumHappy;
				maxAvg=1.0*sumHappy/n;
				ans=tmp;
			}else if(maxHappy==sumHappy){
				if(maxAvg<1.0*sumHappy/n){
					maxAvg=1.0*sumHappy/n;
					ans=tmp;
				}
			}
			num++ ;
		}
		tmp.pop_back();
		return ;
	}
	for(int i=0;i<pre[v].size();i++){
		dfs(pre[v][i],n+1,cost+G[v][pre[v][i]],sumHappy+Happy[v]); 
	}
	tmp.pop_back();
}
int main()
{
	int n,m,val,dist,v,w;
	string a,b;
	cin>>n>>m>>start;
	fill(G[0],G[0]+M*M,INF);
	for(int i=0;i<n-1;i++)   //注意,这里是n-1,不包含起始点
	{
		cin>>a>>val;
		Happy[Code(a)]=val;
	}
	for(int i=0;i<m;i++)
	{	
		cin>>a>>b>>dist;
		v=Code(a);
		w=Code(b);
		G[v][w]=G[w][v]=dist;
	}
	Start=Code(start),ROM=Code("ROM");
	dijk(Start,n);
	dfs(ROM,0,0,0);
	printf("%d %d %d %.0f\n",num,leastcost,maxHappy,maxAvg);
    for(int i=ans.size()-1;i>=0;i--)
    {
        cout<<inttostr[ans[i]];
        if(i!=0) cout<<"->";
    }
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值