题目链接
题目描述
木材厂有 n根原木,现在想把这些木头切割成 k 段长度为l的小段木头(木头有可能有剩余)。
当然,我们希望得到的小段木头越长越好,请求出 l的最大值。
木头长度的单位是 cm,原木的长度都是正整数,我们要求切割得到的小段木头的长度也是正整数。
例如有两根原木长度分别为 11 和 21,要求切割成等长的 6 段,很明显能切割出来的小段木头长度最长为 5。
输入格式
第一行是两个正整数 n,k,分别表示原木的数量,需要得到的小段的数量。
接下来 n 行,每行一个正整数 Li,表示一根原木的长度。
输出格式
仅一行,即l的最大值。
如果连1cm 长的小段都切不出来,输出 0
。
上代码
#include <stdio.h>
#include <stdlib.h>
int find(int *a,int n,int high,int k);
int main()
{
int *a=NULL;
a=(int *)malloc(sizeof(int)*100002);
int n,k;
int high=0;
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
if(a[i]>high)
high=a[i];
}
printf("%d",find(a,n,high,k));
free(a);
return 0;
}
int find(int *a,int n,int high,int k)
{
int low=0,mid,x=0;
int cnt;
while(low<=high)
{
mid=(high-low)/2+low;
if(mid==0) break;
cnt=0;
for(int i=0;i<n;i++)
cnt+=(a[i]/mid);
if(cnt<k)
high=mid-1;
else
{
x=mid;
low=mid+1;
}
}
return x;
}
首先开个大数组(不清楚C语言中10^5能不能直接定义出来)。
int *a=NULL;
a=(int *)malloc(sizeof(int)*100002);
用的是C语言的malloc函数,函数在#include <stdlib.h>头文件中。sizeof()用来求int类型占用几个字节,用4代替sizeof(int)也不是没问题,但是尽量规范一些也不错。
malloc的函数声明大家自行百度,别忘了最后用free()函数释放内存。
int n,k;
int high=0;
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
if(a[i]>high)
high=a[i];
}
n,k是原木的数量和需要得到的小段的数量。high是保存输入原木长度的最大值,
for()循环用来存储树长,顺便找出最高树。
重点来了
int find(int *a,int n,int high,int k)
给大家说说这个函数我的想法。
int find(int *a,int n,int high,int k)
{
//函数的形参对应的是数组地址,树的个数(避免越界),最高树和需要得到的数量.
int low=0,mid,x=0;
//x为返回值
int cnt;
//cnt用来计数,和k比较
while(low<=high)
{
mid=(high-low)/2+low;
//不用mid=(high+low)/2是避免high+low太大越界
if(mid==0) break;
/*
解释下这个判断的作用
如果k值过大,重复循环时会一直执行high=mid-1;
可能出现类似high:8到3到1再到0
当high=0时 mid也为0,无法执行a[i]/mid;
所以此时退出循环,返回x=0;(第四个还是第五个点会用上)
*/
cnt=0;
for(int i=0;i<n;i++)
cnt+=(a[i]/mid);
//计算总共能分几段
if(cnt<k)
high=mid-1;
else
{
/*
cnt>=k,用x保存此时树长 ,然后low=mid+1一步步逼近
如果cnt>=k仍成立,接着存到x里
*/
x=mid;
low=mid+1;
}
}
return x;
//x就是最终每一段长
}