P1902 刺杀大使 广搜+二分
题意:给出一个图,每一个位置有一个伤害值。
现在要从第一行走到最后一行,每走一个格子会伤害(可以从第一行的任意一个位置开始)
伤害的最终值为该人所收到的所有伤害的最大值
问:走完最后一行的全部列的最小值是多大;
思路:根据题目给出的数据范围,遍历整个图需要的复杂度为1e6
但是一次遍历不太可能得出答案;
看到这种求最大值最小,或者最小值最大的题目,我们便可以往二分这个方面想一想
这道题也确实是二分来解,我们确定好范围后,以伤害值为对象,然后根据广搜为判断条件进行二分
那么,我们来详细讲讲这个判断条件
当我们确定一个伤害值去遍历图的时候,凡是遇到大于这个伤害值的,我们就跳过,
把所有能走的点都走一遍,直到能够走到最后一列的其中一个便能退出(因为最后一行的所有数都是0)
假如不能走到最后一行的话,就是不满足
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e3+10; 4 int a[maxn][maxn]; 5 int vis[maxn][maxn]; 6 int nxt[4][2]={ {1,0},{-1,0},{0,1},{0,-1} }; 7 struct node 8 { 9 int x,y; 10 }; 11 int n,m; 12 int check(int mid) 13 { 14 queue<node>q; 15 node tmp; 16 memset(vis,0,sizeof(vis)); 17 for(int i=1;i<=m;i++){ 18 tmp.x=1; 19 tmp.y=i; 20 q.push(tmp); 21 vis[1][i]=1; 22 } 23 while(!q.empty()){ 24 tmp=q.front(); 25 // printf("hahahahhaha:%d %d\n",tmp.x,tmp.y); 26 q.pop(); 27 node step; 28 for(int i=0;i<=3;i++){ 29 step.x=tmp.x+nxt[i][0]; 30 step.y=tmp.y+nxt[i][1]; 31 if(step.x>n||step.x<=0||step.y<=0||step.y>m) continue; 32 if(a[step.x][step.y]>mid) continue; 33 if(vis[step.x][step.y]) continue; 34 q.push(step); 35 vis[step.x][step.y]=1; 36 if(step.x==n) return 1; 37 } 38 } 39 return 0; 40 } 41 int main() 42 { 43 scanf("%d%d",&n,&m); 44 for(int i=1;i<=n;i++) 45 for(int j=1;j<=m;j++){ 46 scanf("%d",&a[i][j]); 47 } 48 int L=0,R=1000; 49 int ans; 50 while(L<=R){ 51 int mid=L+R>>1; 52 // printf("%d\n",mid); 53 if(check(mid)){ 54 R=mid-1; 55 ans=mid; 56 } 57 else{ 58 L=mid+1; 59 } 60 } 61 printf("%d\n",ans); 62 return 0; 63 }