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;}