1. 程式人生 > >二分專題練習(挑戰程式設計)

二分專題練習(挑戰程式設計)

1.最大化最小值

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=5e4+10;
int a[maxn],L,n,m;

bool check(int d){
	int pre=a[0],cnt=0;
	for(int i=1;i<=n;i++){
		if(a[i]-pre<d){
			cnt++;
			continue;
		} 
		pre=a[i];
	}
	if(cnt>m||a[n+1]-pre<d) return false;
	return true;
}

int main(){
	scanf("%d%d%d",&L,&n,&m);
	a[0]=0,a[n+1]=L;
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	sort(a,a+n+1);
	int l=0,r=L+1;    //r的取值要比答案區間大點,所以這裡+1 
	while(r-l>1){   //這裡的答案區間 [l,r) ,所以二分到區間長度為1時,答案就出來了 
		int mid=l+(r-l)/2;
		if(check(mid)) l=mid;
		else r=mid;
	}
	printf("%d\n",l);
	return 0;
}
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=1e5+10;
const int INF=1e9+10;
int a[maxn],n,m;

bool check(int d){
	int sum,p=1;
	for(int i=1;i<=m;i++){
		sum=a[p++];
		while(p<=n&&sum+a[p]<=d){
			sum+=a[p++];
		}
		if(p>n) return true;
	}
	return false;
}

int main(){
	scanf("%d%d",&n,&m);
	int mx=0;
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		mx=max(mx,a[i]);
	}
	int l=mx,r=INF,ans=mx;   
	while(r-l>=0){   //這裡的答案區間 [l,r] ,所以二分到區間長度為空時,答案就出來了 
		int mid=l+(r-l)/2;
		if(check(mid)){
			ans=mid;
			r=mid-1;	
		}else l=mid+1;
	}
	printf("%d\n",ans);
	return 0;
}

/*
7 5
10 10 10 10 10 10 10

1 1
10000
*/

最大化平均值

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int maxn=1e3+10;
const double eps=1e-6;
int a[maxn],b[maxn];
double y[maxn];
int n,k;


bool check(double x){
	for(int i=0;i<n;i++){
		y[i]=a[i]-x*b[i];
	}
	sort(y,y+n);
	
	double sum=0;
	for(int i=n-1;i>=k;i--){
		sum+=y[i];
	}
	return sum>=0;
}

int main(){
	while(~scanf("%d%d",&n,&k)){
		if(n==0&&k==0) break;
		for(int i=0;i<n;i++)
			scanf("%d",&a[i]);
		for(int i=0;i<n;i++)
			scanf("%d",&b[i]);
			
		double lb=0,rb=1;
		while(fabs(rb-lb)>=eps){
			double mid=lb+(rb-lb)/2;
			if(check(mid)) lb=mid;
			else rb=mid;
		}
		printf("%.0f\n",100*lb);
	}
	return 0;
}

poj3111

最小化第k大的值

poj3579: