题目如图所示:
为了避免处理小数误差,将数据*100处理,二分查找找到测试长度,然后直到二分区间左右端点相邻,再测试哪个端点满足要求,最后换成保留2位小数处理。
如下:
//
// testb.c
// testB
//
// Created by ke tang on 2018/9/19.
// Copyright © 2018年 ke tang. All rights reserved.
//
#include <stdio.h>
#include "stdlib.h"
int numvalid (float,int,int,int*);
int numvalid (float mid,int n,int m,int* array)//测试当前测试长度是否可以满足截取数量的要求
{
int numof = 0;
for(int i=0;i<n;i++)
{
numof+=*array/mid;
array = array + 1;
}//numof表示可以截出的小木棍数量
if (numof >= m )
{
return 1;//表示当前测试长度可行,但也许有更长的测试长度能通过
}
else //测试长度过长
{
return 0 ;
}
}
int main()
{
int n,m;//n=给定木棍数量,m=要截出的小木棍长度
int i;
int *array;
int min;
printf("input n and m\n");
scanf("%d%d",&n,&m);
array = (int*)malloc(n*sizeof(int));
printf("input each length of stick\n");
for(i=0;i<n;i++)
{
scanf("%d",&array[i]);
array[i]=100*array[i];
}//存入数组
min=array[0];//n根木棍中的最小值
for (i=1;i<n;i++)
{
if (min>array[i])
min=array[i];
}//取得最小值
//initial
int minlength = 0;//二分查找区间的左端
int maxlength = min;//二分查找区间的右端
int mid = min ;
int ans,ansleft,ansright;
while (minlength+1<maxlength)//二分查找区间左右端点相邻时停止
{
mid= (minlength+maxlength)/2;
ans =numvalid(mid,n,m,&array[0]);
if(ans==0)
{
maxlength = mid;
}
else if (ans == 1)
{
minlength= mid;
}
}
//最后判断二分区间的哪个端点满足数量条件
ansleft = numvalid(minlength, n, m, &array[0]);
ansright = numvalid(maxlength, n, m, &array[0]);
if (ansright == 1&&ansleft==1)//两端均满足时,取大
{
printf("%.2f\n",((float)maxlength/100));
free(array);
}
else if (ansleft==1&&ansright!=1)
{
printf("%.2f\n",((float)minlength/100));
free(array);
}
else if (ansleft!=1&&ansright==1)
{
printf("%.2f\n",((float)maxlength/100));
free(array);
}
return 0;
}