洛谷 P1902 刺杀大使
https://www.luogu.org/problem/P1902
JDOJ 1754: 刺杀大使
https://neooj.com/oldoj/problem.php?id=1754
Description
伊朗伊斯兰革命卫队(某恐怖组织)正在策划一起刺杀行动,他们的目标是沙特驻美大使朱拜尔。他们来到了沙特驻美使馆,准备完成此次刺杀,要进入使馆首先必须通过使馆前的防御迷阵。迷阵由n*m 个相同的小房间组成,每个房间与相邻四个房间之间有门可通行。在第n行的m 个房间里有m 个机关,这些机关必须全部打开才可以进入大使馆。而第1 行的m 个房间有m 扇向外打开的门,是迷阵的入口。除了第1 行和第n 行的房间外,每个房间都被使馆的安保人员安装了激光杀伤装置,将会对进入房间的人造成一定的伤害。第i 行第j 列造成的伤害值为p[i][j](第1 行和第n 行的p 值全部为0)。现在伊斯兰革命卫队打算以最小伤害代价进入迷阵,打开全部机关,显然,他们可以选择任意多的人从任意的门进入,但必须到达第n 行的每个房间。一个士兵受到的伤害值为他到达某个机关的路径上所有房间的伤害值中的最大值,整个部队受到的伤害值为所有士兵的伤害值中的最大值。现在,这个恐怖组织掌握了迷阵的情况,他们需要提前知道怎么安排士兵的行进路线可以使得整个部队的伤害值最小。
Input
第一行有两个整数n,m,表示迷阵的大小。
接下来n 行,每行m 个数,第i 行第j 列的数表示p[i][j]。
Output
输出一个数,表示最小伤害代价。
Sample Input
4 2
0 0
3 5
2 4
0 0
Sample Output
3
HINT
【数据范围】
50%的数据,n,m<=100;
100%的数据,n,m<=1000,p[i][j]<=1000。
在这里弱弱地说一句,伊朗伊斯兰革命卫队是正规军,不是恐怖组织...
好了不扯没用的,上题解:
题意分析:
给定一矩阵,找一条从第一行到第n行的路径,使得路径上的最大值最小。
题解:
马上想到二分答案。看到矩阵找路径的题目还应该想到按四个方向搜索。
所以这就是正解了。
二分域就是从0到整个矩阵中的最大值。
写了一个深搜函数,一个判断函数。
大体思路是这样的:判断思路主要是判一个vis数组,假如我们当前的mid值比当前的矩阵值要小,就是符合要求,假如大了就不符合要求,置成1方便以后判断。
然后开始递归深搜。
深搜的参数是横纵坐标,记得新建方向数组,数组的方向是任意的,只要对上就行。
然后对于深搜到的每一个点,按照4个方向枚举,先判断是否越界,然后判断v数组和vis数组,v数组代表搜没搜过,vis数组代表合不合法。假如都满足就继续搜,最后当x到最后一行的时候,flag=1,深搜结束。
这个flag的原理不是很好理解,可以这么想:假如可以正常地搜到终点,就说明mid>=正确答案,假如不能,就说明mid<=正确答案。
最后处理一下二分的细节,输出的应该是右端点。
code:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,m,maxn,flag; int p[1001][1001],vis[1001][1001],v[1001][1001]; int dx[]={1,-1,0,0}; int dy[]={0,0,1,-1}; void check(int x) { for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { if(p[i][j]<=x) vis[i][j]=0; else vis[i][j]=1; } } void dfs(int x,int y) { if(x==n) { flag=1; return; } for(int i=0;i<4;i++) { int xx=x+dx[i]; int yy=y+dy[i]; if(xx>0 && yy>0 && xx<=n && yy<=m) { if(v[xx][yy]==0 && vis[xx][yy]==0) { v[xx][yy]=1; dfs(xx,yy); if(flag==1) break; } } } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { scanf("%d",&p[i][j]); maxn=max(maxn,p[i][j]); } int l=0; int r=maxn; while(l<r-1) { int mid=(l+r)>>1; flag=0; check(mid); memset(v,0,sizeof(v)); dfs(1,1); if(flag) r=mid; else l=mid; } printf("%d",r); return 0; }