bzoj2143 飞飞侠 最短路

来源:互联网 发布:php 模拟http请求 编辑:程序博客网 时间:2024/05/17 09:04

       用d[i][j][k]表示走到第(i,j)格,在不弹射的情况下还能再走k步的最小花费,那么有转移:

       d[i][j][k]->d[x][y][k-1],其中(i,j)和(x,y)相邻或相等,k>0,表示走到相邻一格或不走;

       d[i][j][0]+a[i][j]->d[x][y][b[i][j]],表示一次弹射。

       注意样例输入的A,B数组相反?另外听说卡spfa?

AC代码如下:

#include<iostream>#include<cstdio>#include<cstring>#include<queue>#include<algorithm>#define N 155#define inf 1000000000using namespace std;const int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1};int m,n,len,x1,x2,x3,y1,y2,y3,t1,t2,t3,a[N][N],b[N][N],d[N][N][N<<1];bool vis[N][N][N<<1];struct node{ int x,y,z,d; };priority_queue<node> q;bool operator <(node u,node v){ return u.d>v.d; }void solve(int sx,int sy){int i,j,k; while (!q.empty()) q.pop();for (i=1; i<=m; i++)for (j=1; j<=n; j++)for (k=0; k<=len; k++){vis[i][j][k]=0; d[i][j][k]=inf;}d[sx][sy][0]=0;node u,v; u.x=sx; u.y=sy; u.z=u.d=0; q.push(u);while (!q.empty() && !(vis[x1][y1][0] && vis[x2][y2][0] && vis[x3][y3][0])){u=q.top(); q.pop();if (vis[u.x][u.y][u.z]) continue; vis[u.x][u.y][u.z]=1;if (u.z){for (k=0; k<4; k++){i=u.x+dx[k]; j=u.y+dy[k];if (i>0 && i<=m && j>0 && j<=n && u.d<d[i][j][u.z-1]){d[i][j][u.z-1]=v.d=u.d;v.x=i; v.y=j; v.z=u.z-1; q.push(v);}}v=u; v.z--;if (v.d<d[v.x][v.y][v.z]){ d[v.x][v.y][v.z]=v.d; q.push(v); }} else {v=u; v.z=a[v.x][v.y]; v.d+=b[v.x][v.y];if (v.d<d[v.x][v.y][v.z]){d[v.x][v.y][v.z]=v.d; q.push(v);}}}}int main(){scanf("%d%d",&m,&n); int i,j;for (i=1; i<=m; i++)for (j=1; j<=n; j++){scanf("%d",&a[i][j]); a[i][j]=min(a[i][j],max(i-1,m-i)+max(j-1,n-j)+1);len=max(len,a[i][j]);}for (i=1; i<=m; i++)for (j=1; j<=n; j++) scanf("%d",&b[i][j]);scanf("%d%d%d%d%d%d",&x1,&y1,&x2,&y2,&x3,&y3);solve(x1,y1); t2+=d[x2][y2][0]; t3+=d[x3][y3][0];solve(x2,y2); t1+=d[x1][y1][0]; t3+=d[x3][y3][0];solve(x3,y3); t1+=d[x1][y1][0]; t2+=d[x2][y2][0];int ans=min(min(t1,t2),t3);if (ans<inf){puts((ans==t1)?"X":(ans==t2)?"Y":"Z");printf("%d\n",ans);} else puts("NO");return 0;}


by lych

2016.3.4

0 0