最短路——徒弟的下山之路

题干:
徒弟的下山之路

终于到了出师的日子,徒弟需要从山顶的纯阳宫找一条花费最少时间的下山之路。
这座山用一个三角形来表示,从山顶依次向下有n层,第i层有i个可移动的位置,出口在最下层的左边。例如有一座5层的山:

此示例中出口为最下层最左边的1所在位置。山上每个数字代表徒弟路过这个位置需要花费的时间,徒弟下山总时间为路径上数字之和。

徒弟每次可以往左、右、左下、右下四个方向移动,例如徒弟位于第3层的数字5时可以向左走到4,向右走到6;也可以向左下走到1,向右下走到7;
又如徒弟位于第3层的数字6时,可以向左走到5,无法向右;也可以向左下走到7,向右下走到8;

输入格式
第一行一个整数n,表示山的高度
接下来n行,第i行有i个整数,表示徒弟经过这个位置需要的时间(路过每个位置花费的时间不超过10)。

数据约束
对于20%的数据,n=4
对于60%的数据,n<=10
对于100%的数据,n<=1000

输出格式
徒弟下山需要花费的最少时间

样例
input
5
1
3 2
4 5 6
9 1 7 8
1 1 4 5 6
output
11

思路:
开始以为就是一个简单的动态规划解决,结果发现不是这样哒,因为既可以从左边向右边走,又可以从右边向左边走,这里动态规划会循环处理。所以只能换个思路。
其实这就是一个简单的最短路问题,所以只要用求解最短路的方法求解就可以了。
自己套了一个dijkstra,可是最后三个点超时了。不知道原因,先放上代码。

#include <iostream>
#include <queue>
using namespace std;
int map[1001][1001];
int d[1001][1001];
int dy[4] = {
    
    -1, 1, 0, 1}, dx[4] = {
    
    0, 0, 1, 1};
struct P {
    
    
    int x, y, cost;
    bool operator<(const P &a) const {
    
     return cost < a.cost; }
};
struct cmp {
    
    
    bool operator()(P a, P b) {
    
     return a.cost < b.cost; }
};
int main() {
    
    
    int n;
    cin >> n;
    fill(map[0], map[0] + 1001 * 1001 + 1, 0x3f3f3f3f);
    fill(d[0], d[0] + 1001 * 1001 + 1, 0x3f3f3fff);
    for (int i = 1; i <= n; i++) {
    
    
        for (int j = 1; j <= i; j++) {
    
    
            scanf("%d", &map[i][j]);
        }
    }
    d[1][1] = map[1][1];
    priority_queue<P, vector<P>, cmp> q;
    P tmp;
    tmp.x = 1, tmp.y = 1, tmp.cost = map[1][1];
    q.push(tmp);
    while (q.size()) {
    
    
        P p = q.top();
        q.pop();
        if (d[p.x][p.y] < p.cost)
            continue;
        for (int i = 0; i < 4; i++) {
    
    
            int tx = p.x + dx[i], ty = p.y + dy[i];
            if (d[tx][ty] > map[tx][ty] + p.cost && tx >= 1 && ty >= 1) {
    
    
                d[tx][ty] = map[tx][ty] + p.cost;
                tmp.x = tx, tmp.y = ty, tmp.cost = d[tx][ty];
                q.push(tmp);
            }
        }
    }
    cout << d[n][1] << endl;
    return 0;
}

再放上大佬的代码:

#include <iostream>
#include <queue>
using namespace std;
typedef long long ll;
int mapping[1005][1005],dp[1005][1005];
int directX[5]={
    
    0,0,1,1};
int directY[5]={
    
    -1,1,0,1};//方向数组
struct point{
    
    
    int x,y,time;
}x;
int main(){
    
    
    int n,i,j;
    cin>>n;
    for(i=1;i<=n;i++)
    for(j=1;j<=i;j++) scanf("%d",&mapping[i][j]);
    
    x.x=x.y=1;
    x.time=dp[1][1]=mapping[1][1];
    queue<point> que;
    que.push(x);
    while(!que.empty()){
    
    //bfs
        x=que.front();
        que.pop();
        if(x.time>dp[x.x][x.y]) continue;
        for(i=0;i<4;i++){
    
    
            x.x+=directX[i];
            x.y+=directY[i];
            x.time+=mapping[x.x][x.y];//新结点
            if(mapping[x.x][x.y]&&(dp[x.x][x.y]>x.time||!dp[x.x][x.y])){
    
    //(没有越界&&(可以更新||没更新过))
                que.push(x);
                dp[x.x][x.y]=x.time;
            }    
            x.time-=mapping[x.x][x.y];
            x.x-=directX[i];
            x.y-=directY[i];    //还原为原结点
        }
    }

    cout<<dp[n][1]<<endl;
    return 0;
} 

猜你喜欢

转载自blog.csdn.net/DwenKing/article/details/107884242