原题链接:原题链接
题目描述:首先输入电缆的个数n,和要分的等长份数k,然后分别输入n个电缆的长度length[i],最后要求输出分后电缆的最长长度。
题目思路:这个题要求求最大长度,可以说是一个最值问题,可以用二分法来求。可以求得所有的电缆的总长度sum,所以大致的二分的范围即sum/k,因为如果分后电缆长度大于sum/k,那么k份电缆的总长度就会大于sum。可以在这个范围内对电缆长度进行二分得mid,然后判断按mid所分的份数number是否满足条件,即若所有的(int)(length[i]/mid)求和所的number大于等于k,那么说明电缆长度还可以再大,所以令left=mid;如果小于k,则说明此长度比最大值要大,所以令right=mid;当left与right的误差缩小一定值的时候,就可以输出结果left了。
注意事项:这个题比较坑人的地方就是要求保留两位小数,但c保留时会自动四舍五入,为了避免这个问题可以有两个解决方法:1.用length[i]-0.005,这样如果length[i]=6.666,减去后即为6.661,这样保留结果为6.66,同样若length[i]=6.661,减去后即为6.656,保留后的结果仍然为6.66。2.可以用函数floor,函数的意义是向下取整,先将结果乘以100然后向下取整,再除以100这样就可以避免四舍五入的问题了。
代码部分:
#include<stdio.h>
#include <stdlib.h>
#include <math.h>
#define st 1e-8
double length[10010];
int n;
int m;
int num(double a)
{
int i, number = 0;
for (i = 0; i < n; i++)
number += (int)(length[i] / a);
return number;
}
int main()
{
int i;
scanf("%d%d", &n, &m);
double sum = 0;
int number = 0;
for (i = 0; i < n; i++)
{
scanf("%lf", &length[i]);
length[i] = length[i];
sum = sum + length[i];
}
sum = sum / m;
double right = sum, left = 0, mid;
while (fabs(right - left) > st)
{
mid = (right + left) / 2;
if (num(mid) >= m)
left = mid;
else
right = mid;
}
printf("%.2f\n", float(floor(left * 100)) / 100);
return 0;
}
写的有点急,如果有错误,欢迎在下方留言。
努力努力再努力x