zoukankan      html  css  js  c++  java
  • HDNOIP201404最短路径

    HDNOIP201404最短路径
    难度级别: A; 编程语言:不限;运行时间限制:1000ms; 运行空间限制:51200KB; 代码长度限制:2000000B
    试题描述

        a、b、c是3个互不相等的1位正数,用它们和数字0可以填满一个n行n列的方格阵列,每格中都有4种数码中的一个。填入0的格子表示障碍物,不能属于任何路径。你是否能找出一条从1行1列出发,到达n行n列且代价最小的路径呢?注意:每一格只能走向与之相邻的上、下、左、右的非0且不出界的格子。而所谓路径代价指的是路径经过的所有格子中的数字总和。请你编程求出从1行1列的位置出发到达n行n列的最小路径代价,若无法到达就输出-1。

    输入
    第一行输入数字n。
    接下来的n行每行是一个长度为n的数字串,这n个字符串就构成了一个数字符的方阵。方阵中除了'0'外,最多还可以包含3种数字符。
    输出
    仅有最小代价或-1这一个整数。
    输入示例
    【输入样例1】
    4
    1231
    2003
    1002
    1113
    【输入样例2】
    4
    3150
    1153
    3311
    0530
    输出示例
    【输出样例1】
    10
    【输出样例2】
    -1
    其他说明
    60%的数据,n<10,80%的数据,n<100,100%的数据,n<1000
     

    确实是一道好题。

    1000*1000的最短路可能有些吃力,实测卡时1000s+。那么怎么做呢?

    方阵中除了'0'外,最多还可以包含3种数字符。

    这提醒我们,可以在这上面做些文章。考虑为什么用Heap来优化Dijkstra,是因为有些边很长有些边很短,对于所有入边相同的点,易得它们的距离是递增的。

    算法就水落石出了,用3个单调队列代替Heap,注意每次如何取队头和如何加入队尾。

    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define ren for(int i=first[x];i!=-1;i=next[i])
    using namespace std;
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=1010;
    char A[maxn][maxn];
    int n,d[maxn][maxn],vis[maxn][maxn],idx[maxn],tp;
    struct Point {
        int x,y;
        bool operator < (const Point& ths) {return d[x][y]<d[ths.x][ths.y];}
    };
    queue<Point> q[3];
    int getfront() {
        int c=-1;
        if(q[0].size()) c=0;
        if(q[1].size()&&(c<0||q[1].front()<q[c].front())) c=1;
        if(q[2].size()&&(c<0||q[2].front()<q[c].front())) c=2;
        return c;
    }
    int mx[]={1,-1,0,0},my[]={0,0,1,-1};
    int solve() {
        if(A[1][1]=='0'||A[n][n]=='0') return -1;
        q[idx[A[1][1]]].push((Point){1,1});d[1][1]=A[1][1]-'0';
        while(q[0].size()+q[1].size()+q[2].size()) {
            int t=getfront();int x=q[t].front().x,y=q[t].front().y;q[t].pop();
            if(x==n&&y==n) return d[x][y];
            if(vis[x][y]) continue;vis[x][y]=1;
            rep(dir,0,3) {
                int nx=x+mx[dir],ny=y+my[dir];
                if(nx>=1&&nx<=n&&ny>=1&&ny<=n&&A[nx][ny]!='0'&&d[x][y]+A[nx][ny]-'0'<d[nx][ny]) {
                    d[nx][ny]=d[x][y]+A[nx][ny]-'0';
                    q[idx[A[nx][ny]]].push((Point){nx,ny});                               
                }          
            }                                         
        }
        return -1;
    }
    int main() {
        n=read();
        rep(i,1,n) scanf("%s",A[i]+1);
        memset(idx,-1,sizeof(idx));
        rep(i,1,n) rep(j,1,n) {
            if(idx[A[i][j]]<0&&A[i][j]!='0') idx[A[i][j]]=tp++;
            d[i][j]=1<<30;
        }
        printf("%d
    ",solve());
        return 0;
    }
    View Code
  • 相关阅读:
    [bzoj4721][noip2016]蚯蚓
    [bzoj1112][POI2008]砖块KLO
    [bzoj3196][tyvj1728]普通平衡树
    [bzoj1596][Usaco2008 Jan]电话网络
    [bzoj3371][poj2009][Usaco2004 Mar]Moo University
    [bzoj2208][Jsoi2010]连通数
    郑捷《机器学习算法原理与编程实践》学习笔记(第四章 推荐系统原理)(二)kmeans
    郑捷《机器学习算法原理与编程实践》学习笔记(第四章 推荐系统原理)(一)推荐系统概述
    Python_sklearn机器学习库学习笔记(四)decision_tree(决策树)
    C++STL学习笔记_(1)vector知识
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/4646453.html
Copyright © 2011-2022 走看看