POJ 4083 我爱北大

这道题真的是目前为止见过的最有情怀的题目之一,感觉做完以后就不再爱北大了…

1、因为最后要求输出任意两个路径之间的最短距离,因此我选择使用的Floyd算法(数据比较弱,样例代码是贪心,应该也能过),Floyd算法用一个dis[N][N]数组存储任意两个点之间的距离,用path数组存储路径。

2、Floyd算法用的是动态规划的思想,设置初始数组为题目中所给的任意两个地点之间的距离, 然后每次更新这个二维数组,更新的思路是每次打开一个点k,比较从i到j经过点k的路径和不经过点k的路径,即dis[i][j] 和dis[i][k]+dis[k][j]的大小,取比较小的那个只更新到dis[i][j]中,若经过k比较短,则要更新path路径,把k存到path[i][j]中去,输出的时候再按照顺序找回去就可以了。

3、有个坑爹的地方在于连个地点之间的距离可能会出现多次,要取最短的存进去,然后图是无向图,因此存距离的时候dis[i][j]和dis[j][i]相等,查bug查了好久,果然还是刚接触这种数据结构经验不足。

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<limits.h>
using namespace std;

#define MAXP 33

string place[MAXP];
int dis[MAXP][MAXP]={0};
int path[MAXP][MAXP]={0};
int P,Q,R;

int getNum(string src){
    for(int i=0;i<P;++i){
        if(src==place[i]){
            return i;
        }
    }
    return -1;
}

void workP(){
    scanf("%d",&P);
    for(int i=0;i<P;++i){
        for(int j=0;j<P;++j){
            dis[i][j] = INT_MAX;
            path[i][j] = -1;
        }
    }
    for(int i=0;i<P;++i){
        cin>>place[i];
    }
    for(int i=0;i<P;++i){
        dis[i][i] = 0;
        path[i][i] = i;
    }
}

void debug(){
    for(int i=0;i<P;++i){
        for(int j=0;j<P;++j){
            if(dis[i][j]==INT_MAX)
                cout<<setw(4)<<"-1"<<' ';
            else
                cout<<setw(4)<<dis[i][j]<<' ';
        }
        cout<<endl;
    }
    cout<<endl;
}

void process(){
    for(int k=0;k<P;++k){
        for(int i = 0;i<P;++i){
            for(int j=0;j<P;++j){
                int dis1 = dis[i][j];
                int dis2 = INT_MAX;
                if(dis[i][k]!=INT_MAX && dis[k][j] != INT_MAX){
                    dis2 = dis[i][k]+dis[k][j];
                }
                if(dis2<dis1){
                    dis[i][j] = dis2;
                    path[i][j] = k;
                }
            }
        }
        //debug();
    }

}

void workQ(){
    scanf("%d",&Q);
    while(Q--){
        string p1,p2;
        int dis0;
        cin>>p1>>p2;
        scanf("%d",&dis0);
        int a = getNum(p1),b = getNum(p2);
        if(dis0<dis[a][b]){
            dis[a][b] = dis0;
            dis[b][a] = dis0;
        }
    }
    //debug();
    process();
}

void output(int _x,int _y){
    if (path[_x][_y] == -1){
        cout << "->(" << dis[_x][_y] << ")->" << place[_y];
        return;
    }
    output(_x, path[_x][_y]);
    output(path[_x][_y], _y); 
}

void workR(){
    scanf("%d",&R);
    while(R--){
        string p1,p2;
        cin>>p1>>p2;
        int x = getNum(p1),y = getNum(p2);
        if(x==y){
            cout<<place[x]<<endl;
            continue;
        }
        cout<<place[x];
        output(x,y);
        cout<<endl;
    }
}

int main(){
    workP();
    //debug();
    workQ();
    workR();
    //system("pause");
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值