您的位置:首页 > 其它

电缆分割问题(二分查找的应用)

2015-04-09 12:02 176 查看
课上的小朋友请自己编写..小心相似度。

大二做过的题目绝大部分已经忘了,拿来回忆巩固一下也不错。描述如下:

某地区即将举行区域程序设计比赛,竞赛委员会已经成立并决定举行一次最公平的竞赛, 

他们决定利用星形拓扑结构来连接每个竞赛者的电脑---也即连接这些电脑到一个中心HUB上 

为了达到真正的公平竞赛目的,竞赛委员会主任下令要求:每个竞赛电脑连接到中心HUB的 

电缆必须是一样长的。竞赛委员会联系了一个本地的电缆老板,要求老板为他们提供一定量 

的相同长度的电缆,而且要求电缆长度越长越好。通过调查,电缆老板知道仓库中每根电缆 

的长度(精确到厘米),而且他可以以厘米的精度剪断电缆,但确不知道他能为竞赛委员会 

提供的每根电缆的最大长度是多少? 

你的任务就是:编程求出每根电缆的最大可能的长度。

输入:

第1行,2个整数N和K,N是仓库中的电缆条数,K是竞赛委员会要求的电缆条数。 

其中 1 < N < 10000, 1 < K < 10000 

第2至第N+1行,每行为仓库中的一条电缆的长度,单位为米。

输出:

仅1行,为提供给竞赛委员的电缆最大长度(精确到小数点两位)

分析:先求得最大划分的可能长度m(所有电缆总长度/要求划分的根数k)  然后在0到m之间查找即可.

由于是小数,所以要用二分查找,每次找(left+right)/2的长度看这样划分是否符合要求的根数,如果符合再看是否是最大的可能(即right和left足够接近),不符合继续递归即可。

要注意的是 小数的判断不能用a==b 这样的形式,而要用b-a<C 这样的形式(C可以是足够小的小数,如b-a<0.01)来判断两个数是否接近。

所以这道题就是一个简单的两重条件的二分查找,代码如下:

#include<iostream>
using namespace std;
double a[10001];
double p; //划分的数量
int n,k;
void Search(double left, double right) //二分搜索
{
if(right<0.01) p=0.0; //小于1cm 不可分
else{
double mid=(left+right)/2.0;
int num=0; //用mid来切分得出的电缆根数
for(int i=0;i<n;i++) num+=(int)(a[i]/mid);
if(right-left<0.01 && num==k) p=mid; //找到,结束
else if(num==k) Search(mid,right); //数量符合,但是电缆长度不是最大,说明划分小了,在mid和right中再找。
else if(num>k) Search(mid,right); //电缆数太多,说明划分太小,需要在mid和right中再找。
else Search(left,mid);//电缆数少,说明划分大了,需要在left和mid中再找。
}

}
int main()
{
cin>>n>>k;
for(int i=0;i<n;i++) cin>>a[i];
double length=0.0;
for(int i=0;i<n;i++) length+=a[i]; //计算总长度
Search(0.0, length/k); //length/k为最大的划分长度
printf("%.2f\n",p);
system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  二分查找 搜索