蓝桥杯——分巧克力——二分法


标题: 分巧克力

    儿童节那天有K位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。
    小明一共有N块巧克力,其中第i块是Hi x Wi的方格组成的长方形。

    为了公平起见,小明需要从这 N 块巧克力中切出K块巧克力分给小朋友们。切出的巧克力需要满足:

    1. 形状是正方形,边长是整数  
    2. 大小相同  

例如一块6x5的巧克力可以切出6块2x2的巧克力或者2块3x3的巧克力。

当然小朋友们都希望得到的巧克力尽可能大,你能帮小Hi计算出最大的边长是多少么?

输入
第一行包含两个整数N和K。(1 <= N, K <= 100000)  
以下N行每行包含两个整数Hi和Wi。(1 <= Hi, Wi <= 100000) 
输入保证每位小朋友至少能获得一块1x1的巧克力。   

输出
输出切出的正方形巧克力最大可能的边长。

样例输入:
2 10  
6 5  
5 6  

样例输出:
2

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗  < 1000ms


请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

注意:
main函数需要返回0;
只使用ANSI C/ANSI C++ 标准;
不要调用依赖于编译环境或操作系统的特殊函数。
所有依赖的函数必须明确地在源文件中 #include <xxx>
不能通过工程设置而省略常用头文件。

提交程序时,注意选择所期望的语言类型和编译器类型。

#include<iostream>
using namespace std;
int N,K;
int w[100010],h[100010];
int check(int x)
{
	int a,b,cnt=0;
	for(int i=0;i<N;i++){
		a = h[i]/x;
		b = w[i]/x;
		cnt += a*b;
	if(cnt>=K)
		return 1;
	}
	return 0;
}
int main()
{
	int ans;
	cin>>N>>K;
	for(int i=0;i<N;i++)
		cin>>h[i]>>w[i];
	for(int i=1;i<=100000;i++)// i 表示枚举的边长。 
		if(check(i))
			ans=i;
		else
			break;
	//这样写,最坏的情况是 10W * 10W = 100亿。复杂度肯定不行。想到要是O (N·LOGN)的复杂度就好了。二分法。 
	cout<<ans<<endl;
	return 0;
}

于是变成:

#include<iostream>
using namespace std;
int N,K;
int w[100010],h[100010];
int check(int x)
{
	int a,b,cnt=0;
	for(int i=0;i<N;i++){
		a = h[i]/x;
		b = w[i]/x;
		cnt += a*b;
	if(cnt>=K)
		return 1;
	}
	return 0;
}
int main()
{ 
	cin>>N>>K;
	for(int i=0;i<N;i++)
		cin>>h[i]>>w[i];
	int l=0,r=100000,mid;
/*	while(l<r-1) //两种写法都可以
	{
		mid = (l+r)/2;
		if(check(mid))
			l = mid;
		else
			r = mid;
	} */
	while(l<r) 
	{
		mid = (l+r)/2;
		if(check(mid))
			l = mid;
		else
			r = mid-1;
	}
	cout<<l;
	return 0;
}

洛谷P1873砍树

题目描述

伐木工人米尔科需要砍倒M米长的木材。这是一个对米尔科来说很容易的工作,因为他有一个漂亮的新伐木机,可以像野火一样砍倒森林。不过,米尔科只被允许砍倒单行树木。

米尔科的伐木机工作过程如下:米尔科设置一个高度参数H(米),伐木机升起一个巨大的锯片到高度H,并锯掉所有的树比H高的部分(当然,树木不高于H米的部分保持不变)。米尔科就行到树木被锯下的部分。

例如,如果一行树的高度分别为20,15,10和17,米尔科把锯片升到15米的高度,切割后树木剩下的高度将是15,15,10和15,而米尔科将从第1棵树得到5米,从第4棵树得到2米,共得到7米木材。

米尔科非常关注生态保护,所以他不会砍掉过多的木材。这正是他为什么尽可能高地设定伐木机锯片的原因。帮助米尔科找到伐木机锯片的最大的整数高度H,使得他能得到木材至少为M米。换句话说,如果再升高1米,则他将得不到M米木材。

输入输出格式

输入格式: 
第1行:2个整数N和M,N表示树木的数量(1<=N<=1000000),M表示需要的木材总长度(1<=M<=2000000000)

第2行:N个整数表示每棵树的高度,值均不超过1000000000。所有木材长度之和大于M,因此必有解。

输出格式: 
第1行:1个整数,表示砍树的最高高度。

输入输出样例

输入样例#1:  
5 20 
4 42 40 26 46 
输出样例#1:  
36
 

#include<iostream>
#include<cstring>
#define ll long long
using namespace std;
ll a[1000100];
ll N,M;
bool check(ll x)
{
	ll tmp;
	for(int i=0;i<N;i++)
	{
		if(a[i]>x)
			tmp += a[i]-x;
		if(tmp>=M)
			return true;
	}
	return false;
}
int main()
{
	scanf("%lld%lld",&N,&M);
	ll t=-1;
	for(int i=0;i<N;i++){
		scanf("%lld",&a[i]);
		if(a[i]>t) t=a[i];
	}
	ll l=1,r=t;
	ll mid;
	while(l<r)
	{
		mid = (l+r)>>1;
		if(check(mid))
			l = mid;
		else
			r = mid-1;
	//	cout<<"l: "<<l<<"  r: "<<r<<"  mid: "<<mid<<endl;		
	}
	printf("%lld",l);
	return 0;
}

洛谷P2678 跳石头

题目背景

一年一度的“跳石头”比赛又要开始了!

题目描述

这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石。组委会已经选择好了两块岩石作为比赛起点和终点。在起点和终点之间,有 N 块岩石(不含起点和终点的岩石)。在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达终点。

为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳跃距离尽可能长。由于预算限制,组委会至多从起点和终点之间移走 M 块岩石(不能移走起点和终点的岩石)。

输入输出格式

输入格式: 
第一行包含三个整数 L,N,M ,分别表示起点到终点的距离,起点和终点之间的岩石数,以及组委会至多移走的岩石数。保证L≥1 且 N≥M≥0 。

接下来 N 行,每行一个整数,第 i 行的整数 Di( 0 < Di < L), 表示第 i 块岩石与起点的距离。这些岩石按与起点距离从小到大的顺序给出,且不会有两个岩石出现在同一个位置。

输出格式: 
一个整数,即最短跳跃距离的最大值。

输入输出样例

输入样例#1: 复制 
25 5 2  

11 
14 
17  
21 
输出样例#1: 复制 

说明

输入输出样例 1 说明:将与起点距离为 2 和 14 的两个岩石移走后,最短的跳跃距离为 4 (从与起点距离 17 的岩石跳到距离 21 的岩石,或者从距离 21 的岩石跳到终点)。

另:对于20% 的数据, 0≤M≤N≤10 。

对于 50% 的数据,0≤M≤N≤100 。

对于 100% 的数据, 0≤M≤N≤50,000,1≤L≤1,000,000,000 。

#include<iostream>
#include<cstring>
#define ll long long
using namespace std;
int L,M,N;
int a[50010];
//容易想到二分答案。难点: M 怎么处理?
//我一直在想要移走 M 块 石头,然后用遍历得到的 a[i+1] - a[i] 的最小距离 与 mid 比较。
//但是我们可以:用给定的 mid ,找出 可以移动的石头数量 cnt,如果 cnt 比 M 小,说明 mid 小了。
bool check(int x)
{
	int cnt=0; //能够移走石头的个数
	int last_posi=0;//在跳跃过程中,上一个块的位置
	for(int i=1;i<=N+1;i++)
	{
		while( a[i]-a[last_posi] < x ) // x 是我们假设的答案
			cnt++;i++;	//我们知道了答案可以反推 ==> 没有两块石头之间的距离会小于 x
		last_posi = i;
	}
	if(cnt<M) 
		return true;	//这个判定可以加到for循环里面
	else 
		return false;
}
int main()
{
	cin>>L>>N>>M;
	a[0] = 0; 
	for(int i=1;i<=N;i++)
		cin>>a[i];
	a[N+1] = L;
	int l=1,r=L,mid;
	while(l<r)
	{
		mid = (l+r)>>1;
		if(check(mid))
			l = mid;
		else
			r = mid-1;
	}
	cout<<l;
	return 0;
}

Problem Description

Inhabitants of the Wonderland have decided to hold a regional programming contest. The Judging Committee has volunteered and has promised to organize the most honest contest ever. It was decided to connect computers for the contestants using a "star" topology
 - i.e. connect them all to a single central hub. To organize a truly honest contest, the Head of the Judging Committee has decreed to place all contestants evenly around the hub on an equal distance from it.
To buy network cables, the Judging Committee has contacted a local network solutions provider with a request to sell for them a specified number of cables with equal lengths. The Judging Committee wants the cables to be as long as possible to sit contestants
 as far from each other as possible.
The Cable Master of the company was assigned to the task. He knows the length of each cable in the stock up to a centimeter, and he can cut them with a centimeter precision being told the length of the pieces he must cut. However, this time, the length is not
 known and the Cable Master is completely puzzled.
You are to help the Cable Master, by writing a program that will determine the maximal possible length of a cable piece that can be cut from the cables in the stock, to get the specified number of pieces.

 

Input

The input consists of several testcases. The first line of each testcase contains two integer numbers N and K, separated by a space. N (1 ≤ N ≤ 10000) is the number of cables in the stock, and K (1 ≤ K ≤ 10000) is the number of requested pieces. The first line
 is followed by N lines with one number per line, that specify the length of each cable in the stock in meters. All cables are at least 1 centimeter and at most 100 kilometers in length. All lengths in the input are written with a centimeter precision, with
 exactly two digits after a decimal point.
The input is ended by line containing two 0's.

 

Output

For each testcase write to the output the maximal length (in meters) of the pieces that Cable Master may cut from the cables in the stock to get the requested number of pieces. The number must be written with a centimeter precision, with exactly two digits
 after a decimal point.
If it is not possible to cut the requested number of pieces each one being at least one centimeter long, then the output must contain the single number "0.00" (without quotes).

 

Sample Input

4 11
8.02
7.43
4.57
5.39
0 0


 

Sample Output

2.00
题意:有n条绳子,分成11段相等的,问能使得最长为多长
 

#include <iostream>
#include <algorithm>
using namespace std;
#define LL long long 
#define exp 1e-8
int n,k;
double a[10005],sum;

int judge(double s)//judge 判断二分的每一个值是否符合 
{
	int cnt=0;
	for(int i=0;i<n;i++)
	{
		cnt+=(int)(a[i]/s);//等于说我现在有了答案,我来反推到这个条件符不符合 
	}
	if(cnt>=k)
		return 1;
	return 0;
}

int main()
{
	int i;
	while(cin>>n>>k,n+k)		
	{
		sum=0;
		for(i==0;i<n;i++)
		{
			cin>>a[i];
			sum+=a[i];
		}
		sum=sum/k;//此时的sum是理论上的平均值 
		double l=0,r=sum;//二分答案做,答案从 0~sum  所以就从0~sum进行二分 
		while((r-l)>exp)//由于精度的原因,double型比较大小的话,我们不好直接用一个 > 或者 < ,我们定义一个很小很小的值来进行判断 
		{
			double mid=(l+r)/2;
			if(judge(mid))//如果分多了,那么说明我要的答案要比mid大,所以把mid赋给l 
				l=mid;
			else
				r=mid;
		}
		printf("%.2f\n",l);
	}
	return 0;
}

其他补充:https://blog.csdn.net/Black__wing/article/details/81583832

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值