PAT_A_1087

/*
建立城市名到编号的map,用于构建地图,从而搜索。
建立编号到城市名的表,用于根据搜索到的路线输出。
将出发地的id设置为0,记录ROM的id,剩下的就是地图搜索了。
dijkstra,dfs搜索路线数,同时记录每条路线的happiness和长度,
刷新最短路线、最短路线的路线数、最短路线happiness总和等信息。
*/
#include <iostream>
#include <vector>
#include <string>
#include <map>
using namespace std;


const int MAX=0x3fffffff;


struct way_point //路线探测结构
{
int city; //到达的城市
int cost; //此时的开销
int happy_sum;//到达某个位置时的总快乐值
vector<int> road;//经过的城市,这个属性可以不加,单独设置一个路线存储,节省空间
};


int main()
{
map<string,int> index;//城市名对应的id
vector<string> id_to_name;//id对应的城市名
int **ways; //地图路线
int *happiness;//各个城市的快乐值
int n,k,id_rom,tempi;//n,k,罗马的id,临时数据
string name,name1;//临时城市名称
int i,j;


cin>>n>>k>>name;//输入信息
ways=new int*[n+1];//初始化
for(i=0;i<=n;i++)
{
ways[i]=new int[n+1];
for(j=0;j<=n;j++)
ways[i][j]=MAX;
}
happiness=new int[n+1];
for(i=0;i<=n;i++)
happiness[i]=0;
index[name]=1;//处理出发地
id_to_name.push_back(name);
id_to_name.push_back(name);
happiness[0]=0; //城市编号从1开始
happiness[1]=0;
for(i=2;i<=n;i++)//输入快乐值
{
cin>>name>>tempi; //对城市进行编号 并记录快乐值
index[name]=i;
id_to_name.push_back(name);
happiness[i]=tempi;
if(name=="ROM")
id_rom=i;//记录罗马ID
}
for(i=0;i<k;i++)//输入邻接矩阵
{
cin>>name>>name1>>tempi;
ways[index[name]][index[name1]]=tempi;
ways[index[name1]][index[name]]=tempi;
}






int *dis=new int[n+1];//迪杰斯特拉算法 D[]
int *flag=new int[n+1];//
for(i=0;i<=n;i++)//初始化
{
flag[i]=0;
dis[i]=MAX;
}
dis[1]=0; //源点到源点距离为0
int use=1; //本轮松弛点
int next,min_dis;//
while(use!=0) //dijkstra
{
flag[use]=1;
next=0;
min_dis=MAX;
for(i=1;i<=n;i++)
{
if(dis[use]+ways[use][i]<dis[i])
dis[i]=dis[use]+ways[use][i];
if(dis[i]<min_dis&&flag[i]==0)
{
next=i;
min_dis=dis[i];
}
}
use=next;
}//迪杰斯特拉算法








     /*
     struct way_point //路线探测结构
     {
int city; //到达的城市
int cost; //此时的开销
int happy_sum;//到达某个位置时的总快乐值
vector<int> road;//经过的城市
     };
     */
vector<way_point> way_test;//路线探测,dfs
way_point wt1,wt2,wtd;//临时点1,临时点2,保存最佳路线
int num_ways=0;//路线数


wt1.city=id_rom;//从罗马开始寻找起点
wt1.cost=0;
wt1.happy_sum=happiness[id_rom];
wt1.road.push_back(id_rom);


way_test.push_back(wt1);
wtd.cost=MAX;
while(!way_test.empty())//dfs
{
wt1=way_test.back();
way_test.pop_back();
if(wt1.city==1)//是起点
{


if(wt1.cost<wtd.cost)
{
wtd=wt1;
num_ways=1;
}
else if(wt1.cost==wtd.cost)
{
num_ways++;
if(wt1.happy_sum>wtd.happy_sum||
(wt1.happy_sum==wtd.happy_sum)&&wt1.road.size()<wtd.road.size())
wtd=wt1;
}
}
else //不是起点 从罗马往起点走
{
    //递归思想
    //所有与 wt1.city 有邻接边且在某一最短路径上的点 加入到 way_test 中
for(i=1;i<=n;i++)
{
if(ways[i][wt1.city]!=MAX&&dis[i]+ways[i][wt1.city]==dis[wt1.city])//i在dis[wt1.city]最短路径中
{
wt2.city=i;
wt2.cost=wt1.cost+ways[i][wt1.city];
wt2.happy_sum=wt1.happy_sum+happiness[i];
wt2.road=wt1.road;
wt2.road.push_back(i);
way_test.push_back(wt2);
}
}
}
}


cout<<num_ways<<" "<<wtd.cost<<" "<<wtd.happy_sum<<" "<<wtd.happy_sum/(wtd.road.size()-1)<<endl;//输出数据
for(i=wtd.road.size()-1;i>0;i--)
cout<<id_to_name[wtd.road[i]]<<"->";
if(i>=0)
cout<<id_to_name[wtd.road[i]];


return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值