PAT-All Roads Lead to Rome

  • 原题链接:https://www.nowcoder.com/pat/5/problem/4315
  • 个人公众号:image
  • 一开始写的dfs,但是提交上去之后超时了,所以最后就改成扩充版本的dijkstra算法
  • 首先我们回顾一下基本的dijkstra算法,基本的dijkstra算法是用来计算最短路径的,他的关键在于维护了一个起点到所有点的最短距离d数组,通过每次找到最短距离里买嗯还没有用过的点,来更新我们的d数组。假设我们的终点index是t,那么我们到终点的最短距离就是d[t]
  • 然后我们将问题抽象一下,其实该题就是让算最短路径、并且把最短路径输出、如果最短路径不唯一,那么选择的条件是(在happiness的和最大情况下,经过点尽可能少的情况)
  • 解法:
    • 首先我们考虑怎么记录路径?我们知道每个更新d值的时候,我们会比较上一时刻起点到该点的最短距离和上一时刻到某点的最短距离+某点到该点的距离,取两者最小的更新值。那么我们只要在更新的记录该点上一个时刻的点是谁就ok,这样递归下去,每一个点的上一个点是谁我都清楚,那就可以找到路径了。
    • 其次我们考虑怎么选择最大的happiness,我们是在更新最短路径时,遇到比较的两个路径距离相同时候这是我们选择路径的if条件,同样的道理,我们也可以计算起点到该点最短经历几个点。
    • 最后,我们考虑怎么最路路径有多少条,我们同样对每个点维护一个值count,代表当前情况下,起点到该点最短距离下路径一共有多少条。如果待更新点需要更新,即就是距离绝对小于,那么count[i] = count[k] 当前点的情况,就等于上一个点的情况。如果距离是等于,那么就是这个点的count+上一个点的count值,即就是count[i] += count[k]。如果距离是大于,说明不用更新,所以我们就不用考虑这种情况。
  • 下面是具体的代码,有dfs的代码,也有扩展版本的dijkstra代码
#include <iostream>
#include <cstdio>
#include <map>
#include <string>
#include <cstring>
#include <vector>
using namespace std;
const int max_city_num = 205;
class City{
  public:
    string name;
    int happiness;
};
int calu_route_happiness(int* prenode, int cur_index, City* citys)
{
    int res = 0;
    while(prenode[cur_index] != -1)
    {
        res += citys[cur_index].happiness;
        cur_index = prenode[cur_index];
    }
    return res;
}
int calu_route_nodes(int* prenode, int cur_index)
{
    int res = 0;
    while(prenode[cur_index] != -1)
    {
        res += 1;
        cur_index = prenode[cur_index];
    }
    return res;
}
void display_city_route(int* prenode, int t, City* citys)
{
    vector<string> citys_name;
    do
    {
        citys_name.push_back(citys[t].name);
        //cout<<citys[t].name<<"<-";
        t = prenode[t];
    }while(prenode[t]!=-1);
    citys_name.push_back(citys[0].name);
    for(int i=citys_name.size()-1;i>=0;i--)
    {
        if(i!=0)
        {
            cout<<citys_name[i]<<"->";
        }else{
            cout<<citys_name[i]<<endl;
        }
    }
}
int dijkstra(int city_num, int t, unsigned int cost[max_city_num][max_city_num], City* citys)
{
    unsigned int d[city_num];
    bool used[city_num];
    int prenode[city_num]; //记录之前最短路径中,前一个点是多少
    int same_condition[city_num];
    // 开始初始化
    memset(used, 0, sizeof(used));
    memset(d, 1, sizeof(d));
    for(int i=0;i<city_num;i++)
    {
        prenode[i] = -1;
        same_condition[i] = 1;
    }

    int s = 0;
    d[s] = 0;
    while(true)
    {
        int v = -1;
        // 找到距离起点最近的点
        for(int u=0;u<=city_num;u++)
        {
            if((!used[u]) && (v == -1 || d[u] < d[v]))
            {
                v = u;
            }
        }
        if(v == -1)
        {
            // 所有的点都已经遍历过了
            break;
        }
        used[v] = true;
        for(int u=0;u<=city_num;u++)
        {
            if(d[u] < (d[v] + cost[v][u]))
            {
                continue;
            }else{
                if(d[u] > (d[v] + cost[v][u]))
                {
                    d[u] = (d[v] + cost[v][u]);
                    prenode[u] = v;
                    same_condition[u] = same_condition[v];
                }else{
                    // 两个路径最低花费相同的情况
                    same_condition[u] += same_condition[v];
                    // 判断happiness的值
                    int cur_happiness = calu_route_happiness(prenode, u, citys);
                    int pre_state = prenode[u];
                    prenode[u] = v;
                    int next_happiness = calu_route_happiness(prenode, u, citys);
                    if(cur_happiness < next_happiness)
                    {
                        continue;
                    }
                    if(cur_happiness > next_happiness)
                    {
                        // 不用更新路径
                        prenode[u] = pre_state;
                    }
                    if(cur_happiness == next_happiness)
                    {
                        prenode[u] = pre_state;
                        int cur_nodes = calu_route_nodes(prenode, u);
                        int pre_state = prenode[u];
                        prenode[u] = v;
                        int next_nodes = calu_route_nodes(prenode, u);
                        if(cur_nodes < next_nodes)
                        {
                            prenode[u] = pre_state;
                        }

                    }

                }
            }
            d[u] = min(d[u], d[v] + cost[v][u]);

        }
    }
    int happiness = calu_route_happiness(prenode, t, citys);
    int nodes_num = calu_route_nodes(prenode, t);
    cout<<same_condition[t]<<" "<<d[t]<<" "<<happiness<<" "<<happiness/nodes_num<<endl;
    display_city_route(prenode, t, citys);
    // 返回终点最近的距离值
    return d[t];
}
class Route{
    public:
        vector<int> citys;
        void add(int city)
        {
            citys.push_back(city);
        }
        void remove()
        {
            citys.pop_back();
        }
        int calu_happiness(City* true_citys)
        {
            int sum = 0;
            for(int i=0;i<citys.size();i++)
            {
                sum += true_citys[citys[i]].happiness;
            }
            return sum;
        }
        void display(City* true_citys)
        {
            cout<<true_citys[0].name<<"->";
            for(int i=0;i<citys.size();i++)
            {
                if(i!=citys.size()-1)
                {
                    cout<<true_citys[citys[i]].name<<"->";
                }
                else{
                    cout<<true_citys[citys[i]].name<<endl;
                }
            }
        }
        int get_citys_num()
        {
            return citys.size();
        }
        int calu_cost(unsigned int cost_value_matrix[max_city_num][max_city_num])
        {
            int cost = 0;
            int s = 0;
            for(int i=0;i<citys.size();i++)
            {
                cost += cost_value_matrix[s][citys[i]];
                s = citys[i];
            }
            return cost;
        }
};
class Routes{
    public:
        vector<Route> routes;
        void add(Route route)
        {
            routes.push_back(route);
        }
        void remove()
        {
            routes.pop_back();
        }
        void clear()
        {
            while(routes.size())
            {
                routes.pop_back();
            }
        }
        int size()
        {
            return routes.size();
        }
        Route max_happiness(City* citys)
        {
            int max_value = -1;
            int max_citys_num = 999999999;
            Route target;
            for(int i=0;i<routes.size();i++)
            {
                int cur_value = routes[i].calu_happiness(citys);
                if(max_value < cur_value)
                {
                    max_value = cur_value;
                    target = routes[i];
                    max_citys_num = routes[i].get_citys_num();
                }else{
                    if(max_value == cur_value)
                    {
                        int cur_citys_num = routes[i].get_citys_num();
                        if(max_citys_num > cur_citys_num)
                        {
                            max_citys_num = cur_citys_num;
                            target = routes[i];
                        }
                    }
                }
            }
            return target;
        }
};
void find_nearst_route(int cur_city, int route_value, int target_city, int& minest_value, bool* used, Route& route, Routes& routes, int n, City* citys, unsigned int cost_value_matrix[max_city_num][max_city_num])
{
    if(cur_city == target_city)
    {
        if(route_value == minest_value)
        {
            //cout<<"ADD route_value is "<<route_value<<" route size is "<<routes.size()<<endl;
            routes.add(route);
            return ;
        }else{
            if(route_value < minest_value)
            {
                //cout<<"RESTART route_value is "<<route_value<<" route size is "<<routes.size()<<endl;
                routes.clear();
                routes.add(route);
                minest_value = route_value;
                return ;
            }else{
                if(route_value > minest_value)
                {
                    //cout<<"CONTINUE route_value is "<<route_value<<" route size is "<<routes.size()<<endl;
                    return ;
                }
            }
        }
    }
    for(int i=0;i<n;i++)
    {
        if(used[i] == false)
        {
            // 删除多余的
            if(cost_value_matrix[cur_city][i] > 9999999)
            {
                continue;
            }
            used[i] = true;
            route_value += cost_value_matrix[cur_city][i];
            route.add(i);
            find_nearst_route(i, route_value, target_city, minest_value, used, route, routes, n, citys, cost_value_matrix);
            route.remove();
            route_value -= cost_value_matrix[cur_city][i];
            used[i] = false;

        }
    }
}
int main()
{
    freopen("/home/give/PAT/All_Roads_Lead_Rome.txt", "r", stdin);
    int n, m;
    string start_city_name;
    map<string, int> reflection;
    cin>>n>>m>>start_city_name;
    City citys[max_city_num];
    citys[0].name = start_city_name;
    citys[0].happiness = 0;
    reflection[citys[0].name] = 0;
    int s = 0;
    int t; // name == ROM
    for(int i=1;i<n;i++)
    {
        cin>>citys[i].name>>citys[i].happiness;
        reflection[citys[i].name] = i;
        if(citys[i].name == "ROM")
        {
            t = i;
        }
    }
    unsigned int cost_value_matrix[max_city_num][max_city_num];
    memset(cost_value_matrix, 1, sizeof(cost_value_matrix));
    for(int i=0;i<m;i++)
    {
        string from_name, to_name;
        int cost_value;
        cin>>from_name>>to_name>>cost_value;
        //cout<<from_name<<"  ->  "<<to_name<<" : "<<cost_value<<endl;
        cost_value_matrix[reflection[from_name]][reflection[to_name]] = cost_value;
        cost_value_matrix[reflection[to_name]][reflection[from_name]] = cost_value;
    }
    bool used[max_city_num];
    memset(used, 0, sizeof(used));
    Route route;
    Routes routes;
    int minest_value = dijkstra(n, t, cost_value_matrix, citys);
    //find_nearst_route(0, 0, t, minest_value, used, route, routes, n, citys, cost_value_matrix);
    //Route max_route = routes.max_happiness(citys);
    //cout<<routes.size()<<" "<<max_route.calu_cost(cost_value_matrix)<<" "<<max_route.calu_happiness(citys)<<" "<<max_route.calu_happiness(citys)/max_route.get_citys_num()<<endl;
    //max_route.display(citys);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值