• PAT A1131 Subway Map


    dfs,选择最优路径并输出~

    这道题难度非常炸裂,要求完完整整自己推一遍,DFS才算过关!
    思路:一遍dfs,过程中要维护两个变量,minCnt 中途停靠最少的站。minTransfer需要换成的最少次数
    1 可以这样算出一条线路的换乘次数:在line数组里保存每两个相邻站中间的线路是几号线,从头到尾遍历最终保存的路径,preLine为前一小段线路编号,如果当前的节点和前一个节点组成的这条路的编号和preLine不同,说明有一个换乘,就将cnt+1,最后遍历完累加的cnt即是换乘的次数。
    2 line数组的存储,用二维数组会内存超限,我们用unordered_map<int,int> line存储的方式,第一个int用来存储线路,每次将前四位存储在第一个线路,后四位存储在第二个线路,第二个int用来保存相邻的线路是几号线。
    3 可以这样算出一条线路中途停站的次数,在dfs的时候有个变量cnt,表示当前路线是所需乘的第几个站,每次dfs的时候将cnt加一表示向下遍历一层,cnt就是当前中途停站的次数。
    2 可以这样输出结果:和计算线路换乘次数思路一样,每当preLine和当前line值不同的时候就输出一句话,保存perTransfer表示上一个换乘站,最后不要忘记输出pretransfer和最后一个站之间的路,即使最后一个站不是换乘站。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=10010;
    unordered_map<int,int> line;
    vector<int> g[maxn];
    vector<int> path,tmp;
    bool visit[maxn]={false};
    int minCnt=1e9;
    int minTransferCnt=1e9;
    int st,ed;
    int transfer (vector<int> v) {
        int cnt=0,preLine=0;
        for (int i=1;i<v.size();i++)
        if (line[v[i-1]*10000+v[i]]!=preLine) {
            cnt++;
            preLine=line[v[i-1]*10000+v[i]];
        }
        return cnt;
    }
    void dfs (int v) {
        visit[v]=true;
        tmp.push_back(v);
        if (v==ed) {
            int transferCnt=transfer(tmp);
            if (tmp.size()<minCnt) {
                minCnt=tmp.size();
                minTransferCnt=transferCnt;
                path=tmp;
            }
            else if (tmp.size()==minCnt&&transferCnt<minTransferCnt) {
                minTransferCnt=transferCnt;
                path=tmp;
            }
            visit[v]=false;
            tmp.pop_back();
            return;
        }
        for (int i=0;i<g[v].size();i++) {
            if (visit[g[v][i]]==false) {
                dfs (g[v][i]);
            }
        }
        visit[v]=false;
        tmp.pop_back();
    }
    int main () {
        int N;
        scanf ("%d",&N);
        int k,pre,x;
        for (int i=1;i<=N;i++) {
            scanf ("%d %d",&k,&pre);
            for (int j=1;j<k;j++) {
                scanf ("%d",&x);
                g[pre].push_back(x);
                g[x].push_back(pre);
                line[pre*10000+x]=line[x*10000+pre]=i;
                pre=x;
            }
        }
        int q;
        scanf ("%d",&q);
        for (int i=0;i<q;i++) {
            scanf ("%d %d",&st,&ed);
            fill (visit,visit+maxn,false);
            minTransferCnt=1e9;
            minCnt=1e9;
            tmp.clear();
            dfs (st);
            printf ("%d\n",path.size()-1);
            int preLine=line[path[0]*10000+path[1]];
            int pre=0;
            for (int j=0;j<path.size();j++) {
                if (line[path[j]*10000+path[j+1]]!=preLine) {
                    printf ("Take Line#%d from %04d to %04d.\n",preLine,path[pre],path[j]);
                    pre=j;
                    preLine=line[path[j]*10000+path[j+1]];
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    Codeforces Round #321 (Div. 2) D. Kefa and Dishes(状压dp)
    51 Nod 1500 苹果曼和树(树形dp)
    UVa 557 汉堡
    POJ 2486 Apple Tree(树形dp)
    Codeforces Round #419 (Div. 2) E. Karen and Supermarket(树形dp)
    Codeforces Round #419 (Div. 2) B. Karen and Coffee(经典前缀和)
    Codeforces Round #419 (Div. 2) A. Karen and Morning(模拟)
    Codeforces Round #390 (Div. 2) D. Fedor and coupons(区间最大交集+优先队列)
    Codeforces Round #390 (Div. 2) C. Vladik and chat(dp)
    Codeforces Round #390 (Div. 2) A. Lesha and array splitting
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/12301517.html
Copyright © 2020-2023  润新知