zoukankan      html  css  js  c++  java
  • COJ 0244 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

    题解:好题呀。

    一看题就知道普通的最短路不行,那么就要注意到题目的特殊条件:边权是基本确定的。

    然后就变成一眼题了:用dij的f递增的思想,窝萌维护几个单调队列就行了。然后就只是O(n^2)的辣。

    单调队列的题真是优美啦啦啦~

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<algorithm>
     5 #include<queue>
     6 #include<cstring>
     7 #define PAU putchar(' ')
     8 #define ENT putchar('
    ')
     9 using namespace std;
    10 const int maxn=1000+10,inf=-1u>>1,u[4]={-1,1,0,0},v[4]={0,0,-1,1};
    11 struct par{int x,y;par(int _x=0,int _y=0){x=_x;y=_y;}};
    12 inline int read(){
    13     int x=0,sig=1;char ch=getchar();
    14     while(!isdigit(ch)){if(ch=='-') sig=-1;ch=getchar();}
    15     while(isdigit(ch)) x=10*x+ch-'0',ch=getchar();
    16     return x*=sig;
    17 }
    18 inline void write(int x){
    19     if(x==0){putchar('0');return;}if(x<0) putchar('-'),x=-x;
    20     int len=0,buf[15];while(x) buf[len++]=x%10,x/=10;
    21     for(int i=len-1;i>=0;i--) putchar(buf[i]+'0');return;
    22 }
    23 queue<par>q[4];char a[maxn][maxn];int n,z,b[10],f[maxn][maxn];
    24 int minq(){
    25     int r=0;
    26     if(!q[1].empty()) r=1;
    27     if(!q[2].empty()&&f[q[2].front().x][q[2].front().y]<f[q[r].front().x][q[r].front().y]) r=2;
    28     if(!q[3].empty()&&f[q[3].front().x][q[3].front().y]<f[q[r].front().x][q[r].front().y]) r=3;
    29     return r;
    30 }
    31 void init(){
    32     memset(f,-1,sizeof(f));n=read();
    33     for(int i=1;i<=n;i++)scanf("%s",a[i]+1);
    34     if(a[1][1]=='0'||a[n][n]=='0'){write(-1);return;}
    35     q[0].push(par(0,0));f[0][0]=inf;
    36     b[a[1][1]-'0']=++z;
    37     q[1].push(par(1,1));f[1][1]=a[1][1]-'0';
    38     while(f[n][n]<0&&!(q[1].empty()&&q[2].empty()&&q[3].empty())){
    39         int k=minq(),x=q[k].front().x,y=q[k].front().y;q[k].pop();
    40         for(int d=0;d<4;d++){
    41             int i=x+u[d],j=y+v[d];
    42             if(a[i][j]>'0'&&f[i][j]<0){
    43                 int c=a[i][j]-'0';
    44                 if(!b[c]) b[c]=++z;
    45                 k=b[c];
    46                 q[k].push(par(i,j));
    47                 f[i][j]=f[x][y]+c;
    48             }
    49         }
    50     }write(f[n][n]);
    51     return;
    52 }
    53 void work(){
    54     return;
    55 }
    56 void print(){
    57     return;
    58 }
    59 int main(){init();work();print();return 0;}
  • 相关阅读:
    定时器QTimer
    QDoubleSpinBox浮点型数字调节框
    pyqt5-步长调节器
    字体选择框QFontComboBox
    组合框-下拉选择框QCombox
    复选框QCheckBox
    CMake学习记录--list(列表操作命令)
    CMake命令之list
    make的link_directories命令不起作用
    Linux平台用C++实现事件对象,同步线程
  • 原文地址:https://www.cnblogs.com/chxer/p/4642537.html
Copyright © 2011-2022 走看看