oj- 木棍问题

题目如图所示:

为了避免处理小数误差,将数据*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;
}

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值