程序设计与算法基础---二分算法思想

导读:

  • 时间复杂度-O()
  • 排序算法时间复杂度
  • 二分算法

程序设计与算法基础---二分算法思想_第1张图片

程序设计与算法基础---二分算法思想_第2张图片

程序设计与算法基础---二分算法思想_第3张图片

插入排序:

程序设计与算法基础---二分算法思想_第4张图片

二分查找:

程序设计与算法基础---二分算法思想_第5张图片

程序设计与算法基础---二分算法思想_第6张图片

程序设计与算法基础---二分算法思想_第7张图片

二分法求方程的根:

程序设计与算法基础---二分算法思想_第8张图片

程序设计与算法基础---二分算法思想_第9张图片

例题一:找一对数

程序设计与算法基础---二分算法思想_第10张图片

方法二:排序+二分

程序设计与算法基础---二分算法思想_第11张图片

方法三:

程序设计与算法基础---二分算法思想_第12张图片

程序设计与算法基础---二分算法思想_第13张图片

程序设计与算法基础---二分算法思想_第14张图片

程序设计与算法基础---二分算法思想_第15张图片

课后习题:

1   POJ2456 Aggressive cows 二分

Description

Farmer John has built a new long barn, with N (2 <= N <= 100,000) stalls. The stalls are located along a straight line at positions x1,…,xN (0 <= xi <= 1,000,000,000).

His C (2 <= C <= N) cows don’t like this barn layout and become aggressive towards each other once put into a stall. To prevent the cows from hurting each other, FJ want to assign the cows to the stalls, such that the minimum distance between any two of them is as large as possible. What is the largest minimum distance?

 

Input

  • Line 1: Two space-separated integers: N and C

  • Lines 2..N+1: Line i+1 contains an integer stall location, xi

Output

  • Line 1: One integer: the largest minimum distance

Sample Input

5 3 




9

Sample Output

3

Hint

OUTPUT DETAILS:

FJ can put his 3 cows in the stalls at positions 1, 4 and 8, resulting in a minimum distance of 3.

Huge input data,scanf is recommended.

题目大意

农夫约翰搭了一间有N间牛舍的小屋。牛舍被排在一条线上,第i 号牛舍在xi的位置。但是他的M头牛对小屋很不满意,因此经产互相攻击。约翰为了防止牛之间互相伤害,因此决定把每头牛都放在离其他牛尽量远的牛舍。也就是要最大化最近的两头牛之间的距离。

关于最大化最小值或者最小化最大值的问题,通常用二分搜索法。

解题思路

二分查找可行解 
记住二分的模板,就以这题的二分为标准

代码

//POJ2456
#include 
#include 

using namespace std;

const int maxn = 100010;
int s[maxn];
int n,m;
/* 函数ok()*/
bool ok(int x)
{
    int cnt = 1;
    int tmp = s[0];
    for(int i = 1 ; i < n ; i ++) {
        if(s[i]-tmp >= x) {
            cnt ++;
            tmp = s[i];
        }
    }
    return cnt >= m;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i = 0 ; i < n ; i ++) {
        scanf("%d",&s[i]);
    }
    sort(s,s+n);  //将数组元素进行排序
    int ma = s[n-1]-s[0],mi = 0;
    while(ma > mi) {
        int mid = mi + (ma-mi+1)/2;
        if(ok(mid)) {
            mi = mid;
        }    
        else ma = mid-1;
    }
    printf("%d\n",mi);
    return 0;
}

月度开销:

#include//二分查找 
#include
#include
const int MAX=100010;
using namespace std;
int spent[MAX];
int money[MAX];
int N,M;
bool valid(int a){//分为M段,看每段之和最大值为c是否可行
	int m=1;//目前有m段 
	int s=0;//目前段的和 
	for(int i=0;iM) return false;//如果分成了超过M段,不符合题意 
		if(s+spent[i]>a){//当前段加上下一个月花销和超过最大值c,则段开 
			s=spent[i];//当前段的和就为spend[i] 
			m++;//段数加一 
		} 
		else
			s+=spent[i];//连续月花销没超过c,不分段,累加和 
	}
	return true;
}
int main(){
	cin>>N>>M;
	int R=0;//右端点 
	for(int i=0;i>spent[i];
		money[i]=spent[i];
		R+=spent[i];
	}
	sort(money,money+N);
	int L=money[N-1];//左端点 
	int value;//value为当前最优解 
    while(L<=R){//二分法找最大月度开销的最小值 
    	int mid=L+(R-L)/2;
    	if(valid(mid)){//若mid可行,更改右端点,看有没有更小的 
    	   value=mid;
    	   R=mid-1;
		} 
		else//若mid不可行,更改左端点,mid放大  
	       L=mid+1;
	}
	cout<

 

你可能感兴趣的:(程序设计与算法(C++))