3、防御迷阵(二分+bfs)

一队士兵来到了敌军城外,准备进攻敌城。敌人在城外布置一个防御迷阵,要进入城池首先必须通过城池外的防御迷阵。

迷阵由n*m个相同的小房间组成,每个房间与相邻四个房间之间有门可通行。而第1行的m个房间有m扇向外打开的门,是迷阵的入口。除了第1行和第n行的房间外,每个房间都安装了激光杀伤装置,将会对进入房间的人造成一定的伤害。第i行第j列造成的伤害值为a[i,j]。 (第1行和第n行的a值全部为0)。

现在士兵打算以最小伤害代价通过迷阵,显然,他们可以选择任意多的人从任意的门进入,但必须到达第n行的房间。一个士兵受到的伤害值为他在经过的路径上所有房间的伤害值中的最大值。现在,士兵们掌握了迷阵的情况,他们需要提前知道怎么安排士兵的行进路线可以使得伤害值最小。

输入

第一行有两个整数n,m表示迷阵的大小。 接下来n行,每行m个数,第i行第j列的数表示a[i,j]。 数据范围:n,m≤1000,a[i,j]≤1000

输出

输出一个数,表示最小伤害代价。

样例

输入

 4 2
 0 0 
 3 5 
 2 4 
 0 0 

输出

3

二分+宽度优先搜索

#include<bits/stdc++.h>
using namespace std;
int a[1010][1010];//地图
int n,m;
int l=INT_MAX,r=INT_MIN,mid;
int q[1000100][3];
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
bool f[1010][1010];
bool jud(int v)
{
    memset(f,false,sizeof(f));
    int h=1,t=1;//指针
    q[1][1]=1;//x
    q[1][2]=1;//y
    f[1][1]=true;//标记走过
    int tx,ty;
    while(h<=t)
    {
        for(int i=0;i<4;i++)
        {
            tx=q[h][1]+dx[i];
            ty=q[h][2]+dy[i];
            if(tx>=1&&tx<=n&&ty>=1&&ty<=m&&!f[tx][ty]&&a[tx][ty]<=v)//可以走
            {
                t++;
                q[t][1]=tx;
                q[t][2]=ty;
                f[tx][ty]=true;//标记走过
                if(tx==n)//通过
                return true;
            }
        }
        h++;
    }
    return false;
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    {
    cin>>a[i][j];
    if(i!=1&&i!=n)
    {
        l=min(l,a[i][j]);
        r=max(r,a[i][j]);
    }
    }
    while(l<=r)
    {
        mid=l+r>>1;
        //如果能通过,减少伤害值再次尝试
        if(jud(mid))r=mid-1;
        else l=mid+1;
    }
    cout<<l<<endl;
    return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wpromise_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值