斐波那契数列
递归算法实现,注意出口 条件 返回
非递归 可用数组 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);
}
}
其中有引用别人的代码,还在学习中,小白进阶中
()