bzoj 2143:飞飞侠
Submit: 1120 Solved: 389
[Submit][Status][Discuss]
Description
飞飞国是一个传说中的国度,国家的居民叫做飞飞侠。飞飞国是一个N×M的矩形方阵,每个格子代表一个街区。然而飞飞国是没有交通工具的。飞飞侠完全靠地面的弹射装置来移动。每个街区都装有弹射装置。使用弹射装置是需要支付一定费用的。而且每个弹射装置都有自己的弹射能力。我们设第i行第j列的弹射装置有Aij的费用和Bij的弹射能力。并规定有相邻边的格子间距离是1。那么,任何飞飞侠都只需要在(i,j)支付Aij的费用就可以任意选择弹到距离不超过Bij的位置了。如下图 (从红色街区交费以后可以跳到周围的任意蓝色街区。) 现在的问题很简单。有三个飞飞侠,分别叫做X,Y,Z。现在它们决定聚在一起玩,于是想往其中一人的位置集合。告诉你3个飞飞侠的坐标,求往哪里集合大家需要花的费用总和最低。
Input
输入的第一行包含两个整数N和M,分别表示行数和列数。接下来是2个N×M的自然数矩阵,为Aij和Bij 最后一行六个数,分别代表X,Y,Z所在地的行号和列号。
Output
第一行输出一个字符X、Y或者Z。表示最优集合地点。第二行输出一个整数,表示最小费用。如果无法集合,只输出一行NO
Sample Input
4 4
0 0 0 0
1 2 2 0
0 2 2 1
0 0 0 0
5 5 5 5
5 5 5 5
5 5 5 5
5 5 5 5
2 1 3 4 2 2
0 0 0 0
1 2 2 0
0 2 2 1
0 0 0 0
5 5 5 5
5 5 5 5
5 5 5 5
5 5 5 5
2 1 3 4 2 2
Sample Output
Z
15
【范围】
100% 1 < = N, M < = 150; 0 < = Aij < = 10^9; 0 < = Bij < = 1000
15
【范围】
100% 1 < = N, M < = 150; 0 < = Aij < = 10^9; 0 < = Bij < = 1000
朴素建图的话虽然点数是m*n的,但是每个点的出边也是n*m的,显然受不了。。。
但是如果分层建图的话,虽然点是n*m*(n+m)的,但是每个点的出边数最多只有5。
所以用d[i][j][k]表示当前在(i,j)点,且最多可再免费走K次的最短路。
本题常数血大,一开始写spfa被卡成儿子,,,后来写dij也被卡成儿子。。。
最后加了一点小优化才过,,,,
/************************************************************** Problem: 2143 User: JYYHH Language: C++ Result: Accepted Time:13916 ms Memory:93240 kb ****************************************************************/ #include<bits/stdc++.h> #define ll long long #define inf 10000000000000000ll #define maxn 155 using namespace std; ll d[maxn][maxn][405]; bool iq[maxn][maxn][405]; char pos[4]={'A','X','Y','Z'}; int px[4],py[4],n,m; ll a[maxn][maxn],ans=inf; ll to[5][5]; int b[maxn][maxn],mxp=0; int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; struct node{ int x,y,z,dis; bool operator <(const node& y)const{ return dis>y.dis; } }; priority_queue<node> q; inline void spfa(int y){ memset(d,0x3f,sizeof(d)); memset(iq,0,sizeof(iq)); node x,z; d[px[y]][py[y]][0]=0,q.push((node){px[y],py[y],0,0}); while(!q.empty()&&(!iq[px[1]][py[1]][0]||!iq[px[2]][py[2]][0]||!iq[px[3]][py[3]][0])){ x=q.top(),q.pop(); if(iq[x.x][x.y][x.z]) continue; iq[x.x][x.y][x.z]=1; z=x,z.z=b[x.x][x.y],z.dis=x.dis+a[x.x][x.y]; if(z.dis<d[z.x][z.y][z.z]){ d[z.x][z.y][z.z]=z.dis; q.push(z); } if(x.z){ for(int i=0;i<4;i++){ z=(node){x.x+dx[i],x.y+dy[i],x.z-1,x.dis}; if(z.x>=1&&z.x<=n&&z.y>=1&&z.y<=m&&z.dis<d[z.x][z.y][z.z]){ d[z.x][z.y][z.z]=z.dis; q.push(z); } } } } while(!q.empty()) q.pop(); for(int i=1;i<=3;i++) to[y][i]=min(d[px[i]][py[i]][0],d[px[i]][py[i]][1]); } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ scanf("%d",&b[i][j]); int fat=max(i,n-i+1)+max(j,m-j+1); b[i][j]=min(b[i][j],fat); } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%lld",&a[i][j]); for(int i=1;i<=3;i++) scanf("%d%d",px+i,py+i); for(int i=1;i<=3;i++) spfa(i); ll now; for(int i=1;i<=3;i++){ now=to[1][i]+to[2][i]+to[3][i]; if(now<ans) ans=now,mxp=i; } if(ans>=inf) puts("NO"); else printf("%c\n%lld\n",pos[mxp],ans); return 0; }
我爱学习,学习使我快乐