1087Dijkstra+DFS

这一生的挚爱 提交于 2019-11-30 02:40:34
初始思路:问题所在
//思路:Dijkstra算法,找最短路径,   点权:最大,如果多种,则给出平均点权最大的路径。
//实现:字符串对应编号处理;————————终点是ROM————记录。
//      求最大happy————满足路径上的传递————最优子结构:

//要求:记录中间路径, 记录最短路径数目。
//补不足:边权点权的初始化,递推


//改正:彻彻底底弄清题意:cost最少的路径,多条则happy总和最大,
//多条则路径的平均距离最小--->保证最小。------->所以DFS实现。


//1003---->对比
#include<bits/stdc++.h>
#define MAXN 205
#define inf 0x3fffffff
using namespace std;

int e[MAXN][MAXN], d[MAXN], happy[MAXN], h[MAXN], num[MAXN];
vector<int> path;
bool vis[MAXN];
int n, k, nummember;
map<int, string> is;
map<string, int> si;

int change(string s){
    if(si.find(s)!=si.end())
        return si[s];
    else{
        si[s] = nummember;
        is[nummember] = s;
        return nummember++;
    }
}

int main(){
    string start;
    cin >> n >> k >> start;
    int s = change(start), endnum;
    for(int i = 1; i < n; i++){                             //-----> 可用一个自动排序替换。
        int hy;
        string station;
        cin >> station >> hy;
        int num = change(station);
        if(station == "ROM") endnum = num;
        happy[num] = hy;
    }
    for(int i = 0; i < k; i++){
        string s1, s2;
        int n1, n2, cost;
        cin >> s1 >> s2 >> cost;
        n1 = si[s1];
        n2 = si[s2];
        e[n1][n2] = e[n2][n1] = cost;
    }
    fill(d, d+MAXN, inf);
    d[s] = 0;
    fill(vis, vis+MAXN, false);
    num[s] = 1; //边权,点权的初始化。
    h[s] = happy[s];

    for(int j = 0; j < n; j++){
        int u = -1, mind = inf;
        //节点从0到n-1
        for(int i = 0; i < n; i++){
            if(vis[i] == false && d[i] < mind){
                u = i;
                mind = d[i];
            }
        }
        if(u == -1) break;
        vis[u] = true;
        path.push_back(u);
        if(u == endnum) break;

        //递推出现了问题,距离d没有更新。
                                      //重点:递推在哪,实现什么
        for(int i = 0; i < n; i++){  //点权,边权,递推在优化的这里:一个点可被多次优化。
            if(vis[i] == false && e[u][i] && d[i] > d[u]+e[u][i]){
                d[i] = d[u] + e[u][i];
                num[i] = num[u];  //递推:最优子结构
                h[i] = h[u]+happy[i];
            }else if(vis[i] == false && e[u][i] && d[i] == d[u]+e[u][i]){
                num[i] += num[u];
                if(h[i] < h[u] + happy[i])
                    h[i] = h[u] + happy[i];
            }
        }
    }
    cout << num[endnum] << " " << d[endnum] << " " << h[endnum] << " " << h[endnum]/path.size() << endl;
    for(int i = 0; i < path.size(); i++){
        if(!i) cout << is[path[i]];
        else cout <<"->" << is[path[i]];
    }

    return 0;
}

整理之后AC代码:
//修改---->自己写:Dijkstra+DFS   ------> 对比1020
//解决的是:先解决cost--->最短路径找到----->Dijkstra
//          然后找到满足点权的路径--------->DFS


#include<bits/stdc++.h>
#define MAXN 205
#define inf 0x3fffffff
using namespace std;

int e[MAXN][MAXN], d[MAXN], happy[MAXN];
vector<int> path, temppath;
vector<int> pre[MAXN];
bool vis[MAXN];
int n, k, maxave = -1, maxsum = -1;                                     //错因:读懂题目真的很重要
map<int, string> is;
map<string, int> si;

int cnt = 0;//求最短路径数目

void DFS(int num){
    temppath.push_back(num);
    if(num == 1){
        cnt++;
        int sum = 0;
        for(int i = 0; i < temppath.size(); i++){
            sum += happy[temppath[i]];
        }
        if(sum > maxsum){
            maxsum = sum;
            path = temppath;
            maxave = sum / (temppath.size()-1);                               //错因:缺少maxave的初始化
        }else if(sum == maxsum){
            if(sum / temppath.size() > maxave){
                maxave = sum / (temppath.size()-1);                          //错因:起始点为0,不计入总求平均值中
                path = temppath;
            }
        }
        temppath.pop_back();
        return;
    }
    for(int i = 0; i < pre[num].size(); i++)
        DFS(pre[num][i]);
    temppath.pop_back();
}


int main(){
    string start;
    cin >> n >> k >> start;
    si[start] = 1;
    is[1] = start;

    for(int i = 2; i <= n; i++){                             //-----> 可用一个自动排序替换。
        int hy;
        string station;
        cin >> station >> hy;
        si[station] = i;
        is[i] = station;
        happy[i] = hy;
    }
    for(int i = 0; i < k; i++){
        string s1, s2;
        int n1, n2, cost;
        cin >> s1 >> s2 >> cost;
        n1 = si[s1];
        n2 = si[s2];
        e[n1][n2] = e[n2][n1] = cost;
    }
    fill(d, d+MAXN, inf);
    d[1] = 0;
    fill(vis, vis+MAXN, false);

    for(int j = 0; j < n; j++){
        int u = -1, mind = inf;
        //节点从1到n
        for(int i = 1; i <= n; i++){
            if(vis[i] == false && d[i] < mind){
                u = i;
                mind = d[i];
            }
        }
        if(u == -1) break;
        vis[u] = true;

        for(int i = 1; i <= n; i++){  //点权,边权,递推在优化的这里:一个点可被多次优化。
            if(vis[i] == false && e[u][i] && d[i] > d[u]+e[u][i]){
                d[i] = d[u] + e[u][i];
                pre[i].clear();
                pre[i].push_back(u);
            }else if(vis[i] == false && e[u][i] && d[i] == d[u]+e[u][i]){
                pre[i].push_back(u);
            }
        }
    }

    int num = si["ROM"];
    DFS(num);

    cout << cnt << " " << d[num] << " " << maxsum << " " << maxave << endl;
    for(int i = path.size()-1; i >= 0; i--){
        if(i==path.size()-1) cout << is[path[i]];
        else cout <<"->" << is[path[i]];
    }

    return 0;
}





标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!