练习 二分 疯牛 派 何中跳房子

斐波那契数列
递归算法实现,注意出口 条件 返回
非递归 可用数组 a[i]=a[i-1]+a[i-2]; 再返回
或用三个变量交换数值,t=f+s;f=s;s=t;(1,2,3)

农夫 John 建造了一座很长的畜栏,它包括N (2≤N≤100,000)个隔间,这 个隔间,这
些小隔间的位置为x 0 ,…,x N-1 (0≤x i ≤1,000,000,000, 均为整数, 各不相同).
John的 的C (2≤C≤N)头牛每头分到一个隔间。牛都希望互相离得远点省得 头牛每头分到一个隔间。牛都希望互相离得远点省得
互相打扰。怎样才能使任意两头牛之间的最小距离尽可能的大,这个最
大的最小距离是多少呢
百练 2456:Aggressive cows
http://bailian.openjudge.cn/practice/2456
二分的算法 设全局变量 a[100005],n,c,
while(low<=high)
{
d=low+(high-low)/2;
if (chearch(d)) low=d+1;
else high=d-1;
}
int chearch(int d)
{
int i, j,pre=0;
for (i=1;i<c;i++)\ 判断牛能否全部放入,按照此间距,是否超界限
{
j=pre+1; \第一头牛,放在第一个0号位置 则下面从1号位置放
while(j<n&&(a[pre]+d)>a[j]) j++; 若从上一个位置加上d后比下一个位置的数大则加一
if (j>=n) return false;\判断是否全部的放进去了
else return true;
}
}
或可按照
cow=1;pre=0;
for (i=1;i<n;i++)
{
if (a[i]-a[pre]>=0) { cow++;pre=i; }
}
if(cow>=c) return true;
else return false;

完整代码
/

#include <stdio.h>
	#include <algorithm>
	#include <iostream>
	#include <stdlib.h>
int chearch(int d,int a[],int c,int n);
using namespace std;
int main()
{
	int n,c,i,j;
	scanf("%d",&n);
	scanf("%d",&c);
	int a[100005];
	for (i=0;i<n;i++)
	{
		scanf("%d",&a[i]);
	}
	sort(a,a+n);
	int low=a[0],high=a[n-1];
	int d;
	while(high-low>1)//此处不能用r>l控制,就算是重新定义一个变量暂存l,提交仍然答案错误
	{
		d=low+(high-low)/2;
		if(chearch(d,a,c,n)) 
			low=d;
		else high=d;
	}
	printf("%d",low);
	system("pause");
	return 0;
}
int chearch(int d,int a[],int c,int n)
{
	int cow=1,pre=0;
	int i;
	for (i=0;i<n;i++)//用牛舍的数量来就对,i从1还是0开始无所谓
	{
		if (a[i]-a[pre]>=d) 
		{
			cow++;pre=i;//用牛的数量c就不对
		}
	}
	if (cow>=c) return true;
	else return false;
}

二分可用来找最大化最小值
为了防止(low +high)过大溢出 可int mid= low+(high-low)/2;

01:派
http://icpcsummer.openjudge.cn/2018hw1/01/
查看 提交 统计 提问
总时间限制: 1000ms 内存限制: 65536kB
描述
我的生日要到了!根据习俗,我需要将一些派分给大家。我有N个不同口味、不同大小的派。有F个朋友会来参加我的派对,每个人会拿到一块派(必须一个派的一块,不能由几个派的小块拼成;可以是一整个派)。

我的朋友们都特别小气,如果有人拿到更大的一块,就会开始抱怨。因此所有人拿到的派是同样大小的(但不需要是同样形状的),虽然这样有些派会被浪费,但总比搞砸整个派对好。当然,我也要给自己留一块,而这一块也要和其他人的同样大小。

请问我们每个人拿到的派最大是多少?每个派都是一个高为1,半径不等的圆柱体。

输入
第一行包含两个正整数N和F,1 ≤ N, F ≤ 10 000,表示派的数量和朋友的数量。
第二行包含N个1到10000之间的整数,表示每个派的半径。
输出
输出每个人能得到的最大的派的体积,精确到小数点后三位。
样例输入
3 3
4 3 3
样例输出
25.133

#include <stdlib.h>
#include <iostream>
using namespace std;
int n,f,sum;
double a[10005];
double low,high,mid;
int incearch(double mid)
{
int b=0,i;
for (i=1;i<=n;i++)
{
b=b+a[i]/mid;//此派的体积除以要作为要分出去的体积看能分几个人,循环相加后,再返回总人数
}
return b;
}
int main()
{
int i;
scanf("%d%d",&n,&f);
low=0,high=0;
for (i=1;i<=n;i++)
{
scanf("%lf",&a[i]);
a[i]=a[i]*a[i]*3.1415926535897932*100000; //将数组中的半径就换 //成其体积,并将最大值放到high 中
high=max(high,a[i]);//*100000是为了讲浮点数转换成整数,不然精       //度有问题
}
//sort(a,a+n);//但不知道为什么用sort排序不对
//high=a[n];
sum=0;
while(low<high)
{
mid=(high+low)/2;
sum=incearch(mid);//返回的算出的总人数
if(sum>=f+1) low=mid;
// 与实际的人数相比,f+1(自己),若人数比实       //际多则说明这种//分法可以,则半径可以变大
else high=mid;//否则说明半径太大,分的人数不到实际人数
if(high-1<low) break;//超界限,让两者不会出现向碰的现象
}
if (incearch(high)==f+1) 
printf("%.3lf",high/100000);
else printf("%.3lf",low/100000);
system("pause");
return 0;
} 

河中跳房子
http://icpcsummer.openjudge.cn/2018hw1/02/
描述
每年奶牛们都要举办各种特殊版本的跳房子比赛,包括在河里从一个岩石跳到另一个岩石。这项激动人心的活动在一条长长的笔直河道中进行,在起点和离起点L远 (1 ≤ L≤ 1,000,000,000) 的终点处均有一个岩石。在起点和终点之间,有N (0 ≤ N ≤ 50,000) 个岩石,每个岩石与起点的距离分别为Di (0 < Di < L)。
在比赛过程中,奶牛轮流从起点出发,尝试到达终点,每一步只能从一个岩石跳到另一个岩石。当然,实力不济的奶牛是没有办法完成目标的。
农夫约翰为他的奶牛们感到自豪并且年年都观看了这项比赛。但随着时间的推移,看着其他农夫的胆小奶牛们在相距很近的岩石之间缓慢前行,他感到非常厌烦。他计划移走一些岩石,使得从起点到终点的过程中,最短的跳跃距离最长。他可以移走除起点和终点外的至多M (0 ≤ M ≤ N) 个岩石。
请帮助约翰确定移走这些岩石后,最长可能的最短跳跃距离是多少?
输入
第一行包含三个整数L, N, M,相邻两个整数之间用单个空格隔开。
接下来N行,每行一个整数,表示每个岩石与起点的距离。岩石按与起点距离从近到远给出,且不会有两个岩石出现在同一个位置。
输出
一个整数,最长可能的最短跳跃距离。
样例输入
25 5 2
2
11
14
17
21
样例输出
4
提示
在移除位于2和14的两个岩石之后,最短跳跃距离为4(从17到21或从21到25)。
思路: 这是noip2015提高组D2T1,题目并不难,要注意枚举每一个可能的差值,看在移走m个石头的时候能否达到该状态,要注意给的n个石头,需要n+1,a[n]=L。保证终点石头也在序列中。

#include <iostream>
#include <stdlib.h>
using namespace std;
int a[50005];
int l,n,m;
int isnot(int mid)
{
	int i,j=0,cnt=0;
	for (i=1;i<=n;i++)
	{
		if(a[i]-a[j]<=mid)
			cnt++;
		else j=i;
	}
	return cnt;
}
int main()
{
	l=0,n=0,m=0;
	scanf("%d%d%d",&l,&n,&m);
	for (int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	}
	a[++n]=l;//把终点放进去,在最大位上
	int low=0,high=l,mid;
	while(low<=high)
	{
		mid=(low+high)/2;
		if (isnot(mid)>m)  
			high=mid-1;
		else low=mid+1;
	}
	printf("%d",low);
	system("pause");
	return 0;
}			

//在poj中AC的代码

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int l,n,m;
int mid,an;//mid表示最小的距离! 
int a[50010]={0};
bool isok(int mid)
{
    int temp=0,cnt=0;
    for (int i=1;i<=n;i++)
    {
        if(a[i]-temp<mid)
            cnt++;
        else
            temp=a[i];
    }
    if(cnt>m) return false;//要是cnt>m就说明最小距离mid太大啦
    if(l-temp<mid) return false;//判断最后一跳跳的距离要是小于mid的话那是不可以的
    return true;

}
int main()
{
    while(~scanf("%d%d%d",&l,&n,&m))
    {
        for(int i=1;i<=n;i++)
        {
        cin>>a[i];
        }
    sort(a,a+(n+1));
    int low=0,high=l;
    while(low<=high)
    {
        mid=(low+high)/2;
        if(isok(mid))
        {
            low=mid+1;
            an=mid;
        }
        else
            high=mid-1;
    }
    printf("%d\n",an);
    }

}

其中有引用别人的代码,还在学习中,小白进阶中
()

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值