二分
二分法
对一个有序数组:例如 1 2 3 4 5 进行元素查找时,例如查找元素5,如果从头遍历到底,时间复杂度为O(n),但是如果用二分搜索的方法
首先去最中间的值3,3比5小,所以搜索区间移动到[4 5]内,这样一下子就将范围缩小了一半,然后这样一直进行下去直至找到,或者是l>r即为未找到,程序结束
package fir;
public class Main{
public void main(String[] args){
int arr[]={1,2,3,4,5};
int l,r,mid;
l=0;
r=4;
int n=5;
while(l<=r){
mid=(l+r)/2;
if(arr[mid]>n){
l=mid+1;
}
else if(arr[mid]==n){
break;
}
else r=mid-1;
}
}
}
如果你以为二分就这点应用就太low了
二分的进阶应用
题目描述:
Dr.Kong设计的机器人卡多非常爱玩,它常常偷偷跑出实验室,在某个游乐场玩之不疲。这天卡多又跑出来了,在SJTL游乐场玩个不停,坐完碰碰车,又玩滑滑梯,这时卡多又走入一个迷宫。整个迷宫是用一个N * N的方阵给出,方阵中单元格中填充了一个整数,表示走到这个位置的难度。
这个迷宫可以向上走,向下走,向右走,向左走,但是不能穿越对角线。走迷宫的取胜规则很有意思,看谁能更快地找到一条路径,其路径上单元格最大难度值与最小难度值之差是最小的。当然了,或许这样的路径不是最短路径。
机器人卡多现在在迷宫的左上角(第一行,第一列)而出口在迷宫的右下角(第N行,第N列)。
卡多很聪明,很快就找到了这样的一条路径。你能找到吗?
输入描述:
第一行: N 表示迷宫是N*N方阵 (2≤ N≤ 100)
接下来有N行, 每一行包含N个整数,用来表示每个单元格中难度 (0≤任意难度≤120)。
输出描述:
输出为一个整数,表示路径上最高难度与和最低难度的差。
样例输入:
5
1 1 3 6 8
1 2 2 5 5
4 4 0 3 3
8 0 2 3 4
4 3 0 2 1
样例输出:
2
这道题就是一个深度优先搜索问题,但是如果直接深搜每一种情况一定会超时,不如换个想法,我们来枚举难度差,既然是求最小的难度差,我们对难度区间[0,120]遍历,用二分法遍历,首先如果mid=(l+r)/2的难度范围内能满足条件,就不必再遍历[mid,r],如果不能满足条件,就不必遍历[l,mid];因此我们可以用二分的方法缩小遍历的范围,对不必要遍历的难度区间舍去,减少遍历次数,减少时间消耗。
#include<iostream>
#include<cstring>
using namespace std;
int dx[]={0,0,1,-1};
int dy[]={-1,1,0,0};
int map[101][101];
int v[101][101];
bool flag;
int mmax,mmin;
int n;
int l,r,mid;
void dfs(int x,int y){
v[x][y]=1;
if(flag)return ;
if(map[x][y]>mmax||map[x][y]<mmin){
return;
}
if(x==n-1&&y==n-1){
flag=true;
return;
}
for(int i=0;i<4;i++){
if(x+dx[i]<=n-1&&x+dx[i]>=0&&y+dy[i]<=n-1&&y+dy[i]>=0&&!v[x+dx[i]][y+dy[i]]){//走没走过的点 原因:防止死循环
dfs(x+dx[i],y+dy[i]); //例子: 0 0 -> 0 1 -> 0 0
}
}
}
bool c(int d){//用来判断当前难度差的范围内能不能满足条件
for(int i=0;i+d<=120;i++){
memset(v,0,sizeof v);
flag=false;
mmax=i+d;
mmin=i;
dfs(0,0);
if(flag)return true;
}
return false;
}
void solve(){
while(l<=r){
mid=(l+r)/2;
if(c(mid)){
r=mid-1;
}
else l=mid+1;
}
cout << l;
return ;
}
int main()
{
scanf("%d",&n);
memset(map,0,sizeof map);
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
scanf("%d",*(map+i)+j);
}
}
l=0;r=120;
memset(v,0,sizeof v);
solve();
return 0;
}
本文来自博客园,作者:correct,转载请注明原文链接:https://www.cnblogs.com/correct/p/12862123.html

浙公网安备 33010602011771号