思路
题意:求 让蜥蜴没办法达到终点所必须花费的最小总代价
我们通过 把特殊的走道转化为墙壁( 转换代价为g[i][j] ),来使蜥蜴最终无法到达终点
g[i][j]取不同值的意义:-1代表墙壁,0代表走道,而1到10^9之间的正整数代表特殊的走道。
因为 g[i][j] = -1 代表已经是墙壁,故转换代价为 0,因此我们让 g[i][j] = -1的,g[i][j] = 0
而g[i][j] = 0 的 代表无法转换为墙壁,故代价是无穷大,因此我们让 g[i][j] = 0的,g[i][j] = 1e18
因为 蜥蜴在左上角,终点在右下角,要使得蜥蜴无法到达终点 就必须 有 ''一道墙'' 把蜥蜴或者终点给围起来
围墙的位置 有以下四种情况:
到这里,问题便转换为了 建造一面最小花费的围墙,围墙的情况或格式只有四种 :见上面图片
我们用 堆优化dijkstra 来解决问题:
① 所有可能的起点入队 ,起点:围墙的头部 在这里我们规定 头部要么在上端,要么在右端,则尾部 要么在下端,要么在左端 ② 弹出最小花费的点 ,用该点更新 到其后继点的最小花费 若弹出的点 可能作为围墙尾部(在左端或者在下端),用到该点的最小花费,来更新最终答案 ③ 后继点入队
综上,Code 如下 .
Code
#include <bits/stdc++.h> using namespace std; const int N = 510; typedef long long ll; struct node{ int x,y; ll w; bool operator < (const node &x) const{ return w > x.w; } }; int rou[4][2]={-1,0,0,1,1,0,0,-1}; bool st[N][N]; ll g[N][N]; int T,n,m; int main(){ cin>>T>>n>>m; while(T--){ for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { cin>>g[i][j]; if(g[i][j]==0) g[i][j]=1e18; else if(g[i][j]==-1) g[i][j]=0; st[i][j]=false; } priority_queue<node>q; for(int j=2;j<=m;j++) if(g[1][j]!=1e18) q.push({1,j,g[1][j]}) ; for(int i=2;i<n;i++) if(g[i][m]!=1e18) q.push({i,m,g[i][m]}) ; ll res=1e18; while(q.size()){ auto p=q.top(); q.pop(); int x=p.x,y=p.y; ll w=p.w; if(y==1||x==n) { res=min(res,w); //弹出来的一定是最短的边 也即是最小花费的边 continue; } if(st[x][y]) continue; st[x][y]=true; for(int i=0;i<4;i++){ int xi=x+rou[i][0]; int yi=y+rou[i][1]; if(xi<1||xi>n||yi<1||yi>m||g[xi][yi]==1e18) continue; q.push({xi,yi,w+g[xi][yi]}); } } if(res==1e18) puts("-1"); else cout<<res<<endl; } return 0; }