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 }
View Code

 

posted @ 2020-04-13 10:47  古比  阅读(168)  评论(0编辑  收藏  举报