首页 > 其他分享 >1005 迷宫2 思维 消耗最少防止通行 障碍物形成最短路

1005 迷宫2 思维 消耗最少防止通行 障碍物形成最短路

时间:2022-08-17 21:55:56浏览次数:93  
标签:格子 int 短路 迷宫 座标 mp 蜥蜴 1005

链接:https://ac.nowcoder.com/acm/contest/26077/1005
来源:牛客网

题目描述

这是一个关于二维格子状迷宫的题目。迷宫的大小为N*M,左上角格子座标为(1,1)、右上角格子座标为(1,M)、左下角格子座标为(N,1)、右下角格子座标为(N,M)。每一格都用-1到109之间的整数表示,意义分别为:-1为墙壁,0为走道,而1到109之间的正整数代表特殊的走道。
蜥蜴最初位于迷宫的座标(1,1)的格子,每一步蜥蜴只能往上、下、左、右、左上、右上、左下、右下八个方向之一前进一格,并且,他也不能走出迷宫边界。蜥蜴的目的地是走到迷宫的右下角格子,也就是座标位置(N,M)。我们想要动一些手脚,使得蜥蜴没有办法从(1,1)出发并抵达(N,M)。我们学会了一个邪恶的法术,这个法术可以把特殊的走道变成墙壁,施法一次的代价为表示该特殊走道的正整数。
假设,我们可以在蜥蜴出发之前不限次数的使用这个邪恶的法术,所花的总代价即为每次施法代价的总和,蜥蜴出发之后就不能再使用这个法术了,请问让蜥蜴没办法达到终点所必须花费的最小总代价是多少呢?
注意,0所代表的走道是无法变为墙壁的。

输入描述:

输入的第一行有三个正整数Q,N,M。
代表接下来有Q组数据,这Q组数据都是N*M的迷宫。
接下来每组数据各N行,代表一个迷宫,每行各M个整数,第i行中的第j个整数代表迷宫座标(i,j)的格子。

输出描述:

每一组数据输出一行,如果无论如何蜥蜴都能到达终点,请在这一行中输出-1,否则请在这一行中输出一个代表答案的整数。
示例1

输入

复制
3 3 3
0 2 2
3 2 3
2 2 0
0 1 2
-1 1 -1
2 1 0
0 1 2
0 0 0
2 1 0

输出

复制
6
1
-1

备注:

1<=Q<=5*10
3

1<=Q*N*M<=2.5*10
5

1<=N,M<=500
代表迷宫格子的数字为介于-1和10
9
间的整数(包含-1和10
9
)
每个迷宫中,代表座标(1,1)和(N,M)的格子的数字一定是0

 

分析

题意: 障碍物连成一条线,阻止人从左上角走到右下角

细节,大根堆,要先取小的,直接按照 w>x.w排序就可以了

将所有不是障碍物的点看作无穷大(走不了)

将所有是障碍物的点,=-1 的看作0,其它就按照权值来

求从右边或者上面 到达 下面或者左边的 最短路即可

把起点放在队列,如果遇到终点再取最小的花费,最终输出障碍物连成一条路的最短路。

//-------------------------代码----------------------------

//#define int ll
const int N = 5010;
int n,m,q;

int mp[N][N];
bool st[N][N];

struct node {
    int x,y;
    ll w;
    bool operator<(const node & x) const {
        return w>x.w;
    }
};

void solve()
{
    cin>>q>>n>>m;
    fo(k,1,q) {
        fo(i,1,n) {
            fo(j,1,m) {
                cin>>mp[i][j];
                if(mp[i][j] == 0) mp[i][j] = inf;
                if(mp[i][j] == -1) mp[i][j] = 0;
                st[i][j] = 0;
            }
        }
        priority_queue<node> q;
        fo(j,2,m) if(mp[1][j] != inf) q.push({1,j,mp[1][j]});
        fo(i,2,n-1) if(mp[i][m] != inf) q.push({i,m,mp[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] = 1;
            fo(i,0,3) {
                int xi = x + dx[i],yi = y + dy[i];
                if(xi < 1 || xi > n || yi < 1 || yi > m || mp[xi][yi] == inf) continue;
                q.push({xi,yi,w+mp[xi][yi]});
            }
        }
        if(res == 1e18) {None}
        else cout<<res<<endl;
    }
    
}
void main_init() {}
signed main(){
    AC();clapping();TLE;
    cout<<fixed<<setprecision(12);
    main_init();
//  while(cin>>n,n)
//  while(cin>>n>>m,n,m)
//     int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}

/*样例区


*/

//------------------------------------------------------------

 

标签:格子,int,短路,迷宫,座标,mp,蜥蜴,1005
From: https://www.cnblogs.com/er007/p/16596900.html

相关文章

  • CF464E The Classic Problem(线段树 最短路)
    CF464ETheClassicProblem\(\bigstar\texttt{Hint}\):发现没有什么好的突破口?为什么不想想怎样才能实现题目中\(2^x\)的加减法呢?可见每次加减法,我们要做的是将添加的......
  • 严格次短路简单笔记
    严格次短路定义按路径长度从小到大排序,去重后排名第\(2\)的路径就是次短路。显然,链式不存在次短路的,连单向边的树也不存在(想一想,为什么)严格次短路求法这里使用的是SP......
  • 牛客小白月赛54 D-Word(最短路/bfs)
    链接:https://ac.nowcoder.com/acm/contest/38457/D题目描述给你一个包含n个单词的单词表。你需要将单词s以如下操作转换成t。每次改变s的一个字母。你需要保证......