1321. Robot

TAG 最短路

把格按上下左右的连通性转换成图,即格子为顶点,边 (a,b) 的权值为格子b的花费。再用普通的 Dijkstra 算法就可以直接解。

不过这里顶点最多n=10000个,普通的 Dijkstra 算法是O(n^2) 效率太低了。可以用堆优化。

因为在 Dijkstra 处理时候,有3种节点

  1. 已检查的节点。(升序)
  2. 候选节点。
  3. 未处理节点。

我们每次需要从2中选出路径最短的节点进行检查,然后更新2和3中的路径值,把部分3加到2。普通的遍历找最小值需要O(n),显然遍历的次数很多,所以可以用堆优化。

这里有一点比较特殊,就是到达同一个格的花费都是一样的,所以不需要更新节点路径长度值(我们已按升序检查节点)。

程序中我是用priority_queue实现的,

0.02 sec308 KB

效率还不错。。能排在status第一页

贴源码:

/* source code of submission 442918, Zhongshan University Online Judge System */ #include <stdio.h> #include <memory.h> #include <queue> #include <algorithm> using namespace std; const int N=100; struct node { int x,y,cost; bool operator<(const node &y)const { return cost>y.cost; } }; int fuel[N+1][N+1]; bool visited[N+2][N+2]; int n,m,ans; int head,tail; int sx,sy,ex,ey,t; node tmp,tmp2; int abs(int x) { return x<0? -x: x; } int min_d(priority_queue<node> &q) { while ( !q.empty() ) { tmp=q.top(); q.pop(); for (int i=-1; i<=1; ++i) { for (int j=-1; j<=1; ++j) { if ( abs(i+j)!=1 ) continue; if ( !visited[tmp.x+i][tmp.y+j] ) { tmp2.x=tmp.x+i; tmp2.y=tmp.y+j; tmp2.cost=tmp.cost+fuel[tmp.x+i][tmp.y+j]; q.push(tmp2); visited[ tmp2.x][ tmp2.y]=true; if ( tmp2.x==ex && tmp2.y==ey ) { return tmp2.cost; } } } } } return 0; } int main(int argc, char *argv[]) { scanf("%d", &t); while ( t-- ) { scanf("%d%d", &n, &m); for (int i=1; i<=n; ++i) { for (int j=1; j<=m; ++j) { scanf("%d", &fuel[i][j]); } } scanf("%d%d", &sx,&sy); scanf("%d%d", &ex,&ey); memset(visited, false, sizeof(visited)); for (int i=0; i<=n+1; ++i) { visited[i][0]=visited[i][m+1]=true; } for (int i=0; i<=m+1; ++i) { visited[0][i]=visited[n+1][i]=true; } priority_queue<node> q; tmp.x=sx; tmp.y=sy; tmp.cost=fuel[sx][sy]; visited[sx][sy]=true; if ( sx==ex && sy==ey ) { ans=tmp.cost; } else { q.push(tmp); ans=min_d(q); } printf("%d/n", ans ); } return 0; }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值