P1902 刺杀大使(二分+dfs)

1902
题目描述
某组织正在策划一起对某大使的刺杀行动。他们来到了使馆,准备完成此次刺杀,要进入使馆首先必须通过使馆前的防御迷阵。

迷阵由 n×m 个相同的小房间组成,每个房间与相邻四个房间之间有门可通行。在第 nn 行的 m 个房间里有 m 个机关,这些机关必须全部打开才可以进入大使馆。而第 1 行的 m 个房间有 m 扇向外打开的门,是迷阵的入口。除了第 1 行和第 n 行的房间外,每个房间都被使馆的安保人员安装了激光杀伤装置,将会对进入房间的人造成一定的伤害。第 i 行第 j 列 造成的伤害值为 p
ij

(第 1 行和第 n 行的 p 值全部为 0)。

现在某组织打算以最小伤害代价进入迷阵,打开全部机关,显然,他们可以选 择任意多的人从任意的门进入,但必须到达第 nn 行的每个房间。一个士兵受到的伤害值为他到达某个机关的路径上所有房间的伤害值中的最大值,整个部队受到的伤害值为所有士兵的伤害值中的最大值。现在,这个恐怖组织掌握了迷阵的情况,他们需要提前知道怎么安排士兵的行进路线可以使得整个部队的伤害值最小。

输入格式
第一行有两个整数 n,m,表示迷阵的大小。

接下来 n 行,每行 m 个数,第 i 行第 j列的数表示pij 。

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

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
int n, m;
const int maxn = 1005;
int a[maxn][maxn], p[maxn][maxn];
int flag;
int vis[maxn][maxn];
int dx[] = {1, -1, 0, 0}, dy[] = {0, 0, 1, -1};
int cnt;
void change(int x)
{
   for (int i = 1; i <= n; i++)
   {
      for (int j = 1; j < m; j++)
      {
         if (a[i][j] <= x)
            p[i][j] = 1;
         else
            p[i][j] = 0;
      }
   }
}
void dfs(int x, int y)
{
   if (x == n)
   {
      flag = 1;
      return;
   }
   vis[x][y] = cnt;
   for (int i = 0; i < 4; i++)
   {
      int tx = x + dx[i];
      int ty = y + dy[i];
      if (tx > 0 && tx <= n && ty > 0 && ty <= m && vis[tx][ty] != cnt && p[tx][ty])
      {
         vis[tx][ty] = 1;
         dfs(tx, ty);

         if (flag)
            return;
      }
   }
}
int main()
{
   cin >> n >> m;
   int maxx = -100;
   for (int i = 1; i <= n; i++)
   {
      for (int j = 1; j <= m; j++)
      {
         cin >> a[i][j];
      }
   }
   int l = 0, r = 1008;
   int ans;
   while (l <= r)
   {
      int mid = (l + r) >> 1;
      change(mid);
      memset(vis, 0, sizeof(vis));
      cnt++;
      flag = 0;
      dfs(1, 1);
      if (flag == 1)
      {
         ans = mid;
         r = mid - 1;
      }
      else
         l = mid + 1;
   }
   cout << ans << endl;
   return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值