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;}
原文地址:https://www.cnblogs.com/chxer/p/4642537.html