[Dichotomy] examples to explain and train platforms chains -C ++

First, let's understand what half from a game. (Excerpt from the programmer small gray blog )

Why is this the most efficient it? Because every choice numbers, whether too large or too small, can make the rest of the range of options reduced by half.
Given integer ranging from 0 to 1,000:

We chose 500 for the first time, discovered too large, then the next choice, it becomes a 1-499:
Here Insert Picture Description

We chose the second 250, found or too large, then the next choice, it becomes a 1-249: Here Insert Picture Description

We chose the third 125, found too small, then the next choice, it becomes a 126-249: Here Insert Picture Description

By analogy, the worst case need to guess how many times it? The answer is log1000 = 10 times, that is, so that the original scope of section 10 "binary."
So we can easily find, binary search does not occupy more space, but you can make the time complexity of O (log (n)), this speed optimization in the program is very effective reduced from O (n) to.
The second is the code implementation issues.
The basic code first affixed, to see if you can understand:

#include<bits/stdc++.h>
using namespace std;
int a[100+1];
int main()
{
  int x,n;
  cin>>n;
  for(int i=1;i<=n;i++)
  {
    cin>>a[i];
  }
  cin>>x;
  int left=1,right=n;
  while(left<=right)
  {
    int mid=(left+right)/2;
    if(x==mid){cout<<"Find."<<endl<<mid;break;}
    if(mid>x)
    {
      right=mid+1;
    }
    else left=mid-1;
  }
  if(left>right)cout<<"Not find."<<endl;
  return 0;
}

i.e., left to find the left boundary of this range, right Similarly, mid midpoint, is next binary reference point.
If you want to find the number is even smaller than the midpoint (mid), find the next interval is from left ~ mid-1,
if you want to find thanks to a number bigger than the midpoint (mid), find the next interval is from mid + 1 ~ right.
If the left margin (left) bigger than the right border (right), specifies the number of this interval there are no're looking for, that can not be found.
If you want to find the number is equal to the midpoint (mid), that we find the number you are looking for.
If these steps do not understand, please refer to the above cartoon.
Of course, recursion is also achievable:

void binsearch(int left,int right)
{
  if(left<=right)
  {
    int mid=(left+right)/2;
    if (a[mid]==x) {cout<<"Find"<<endl;return;} 
    if (x<a[mid]) binsearch(left,mid-1);
    else binsearch(mid+1,right);
  } 
  else cout<<"Not Find"<<endl;
}

Roughly grasp the concept of the later to see examples;

火车站台连锁店
描述

蒜头君建立了一家火车站台连锁店,要在一条铁路线的所有车站里,选择一部分车站开办连锁店,销售各种口味的大蒜。

铁路线上有 n 个车站,假设这条铁路线是一条直线,其中每个站点的坐标为 x1,x2,x3,x4...xn

蒜头君一共要开办 m 个连锁店,并且不希望连锁店离得太近,以使得整体的收益最大化。他希望他的连锁店之间的最近距离尽可能大,你能帮他算出这个最大的最近距离吗?


输入
第一行输入用空格分隔的两个整数 n,m(2≤n≤10^5,2≤m≤n),分别表示车站数量和连锁店数量。
接下来一共 n 行,每行一个整数 xi,0≤xi≤10^9,表示车站的坐标。


输出
输出一行整数,表示最大的最近距离。


输入样例 1

6 3
1
3
5
2
7
9
输出样例 1

4
输入样例 2

5 4
5
7
10
28
9
输出样例 2

2

I understood that the subject with the first;
in a period of n stations can open position, wherein the select number m, so that the minimum distance between each of the two stations has its maximum value.
Probably means that you have to let the m stations, the distance between each two stations are as large as possible.
This question is dichotomous thinking a bit complicated emm
first half we can not directly because things are they can not find half of

Because the subject of the request and then output the shortest position, I simply put the shortest distance brought half!
But we need a helper function to count to calculate the number of stores can open L is the shortest distance.
Function structure is very simple, direct Tieshanglai:

int count(int l)
{
  int last=1,ans=1;
  for(int i=1;i<=n;i++)
  {
    while(a[i]-a[last]<l)
    {
      i++;
      if(i>n)return ans;
    }
    last=i;
    ans++;
  }
  return ans;
}

Find how to achieve?
1. First, determine the initial scope
because we want the shortest distance binary search, so we need to value one of the most original of left and right. To be sure that the shortest distance L 1 to the maximum at a certain coordinate - minimum coordinates.
2. Simulation lookup process drawing!
Assume that FIG long like this: (n = 5, m = 4)
Here Insert Picture Description
first lookup interval L is 1 to 13. At this time, mid = 7, will be passed to the function mid count, found you can open two stores.
Since 2 <m (4), so that the next search range becomes 1 to 7. (Left = 1, right = 7 )
second lookup interval L is 1 to 7 The mid = 4, will be passed to the function mid count, found to open three stores.
Because 3 <m (4), so that the next search range becomes 1 ~ 4. (Left = 1 , right = 4)
third lookup interval L is 1 to 4. At this time, mid = 2, the mid passed into the function count, it can be found to open five stores.
5≥m because (4), so that the next search interval into 2 ~ 4. (Left = 2 , right = 4)
Fourth lookup interval L is 2 to 4, when mid = 3, the mid incoming function count, can be found to open four stores.
Because 4≥m (4), so look for the next time interval becomes 3 ~ 4 (left = 3, right = 4)
Next, if not stopped, the value of the left and right and the mid never any change!
why?
We dichotomy wording is while(left<right)
so on! I found nothing wrong with it?
Because we dichotomy wording is equal to one each left and right mid, but they are one and equal to the mid time, this becomes an infinite loop!
So we read:

while(right-left>1)

This will be good to avoid this problem!
However, after out-half, we who value the output? right?
This is not entirely correct!
In the shortest possible distance to the right when we got m not open a shop! Because while we are writing, so we have to look at more than judgment:

if(count(right)>=m)cout<<right<<endl;
else cout<<left<<endl;

So when n = 5, m = 4, FIG follows when the digital output should be 3;
Here Insert Picture Description

The complete code is as follows:

#include<bits/stdc++.h>
using namespace std;
int a[100000+1];
int n,m;
int count(int l)
{
  int last=1,ans=1;
  for(int i=1;i<=n;i++)
  {
    while(a[i]-a[last]<l)
    {
      i++;
      if(i>n)return ans;
    }
    last=i;
    ans++;
  }
  return ans;
}
int main()
{
  cin>>n>>m;
  for(int i=1;i<=n;i++)
  {
    cin>>a[i];
  }
  sort(a+1,a+1+n);
  int left=1,right=a[n]-a[1];
  while(right-left>1)
  {
    int mid=(left+right)/2;
    if(count(mid)>=m)
    {
      left=mid;
    }
    else right=mid;
  }
  if(count(right)>=m)cout<<right<<endl;
  else cout<<left<<endl;
  return 0;
}

ov.

Guess you like

Origin www.cnblogs.com/moyujiang/p/11246521.html