POJ No .1064题解
题目Cable master
###题目描述
有 N 条绳子,它们的长度分别为 Li。如果从它们中切割出 K条长度相同的绳子,这 K 条绳子每条最长能有多长?答案保留到小数点后 2 位(直接舍掉 2位后的小数)。
###输入格式
第一行两个整数 N 和 K,接下来 N 行,描述了每条绳子的长度 Li
###输出样例
输入:4 11 输出: 2.00
8.02
7.43
4.57
5.39
###说明/提示
对于 100%100% 的数据 0<Li <=100000.00, 0<n<10000,0<n≤10000,0<k≤10000
该题在洛谷也有整形的
整形二分题目链接
整形题解
题目用二分搜索可以容易求得答案
条件:
C(x) = 可以得到K条长度为x的绳子
则该问题转变为求满足条件的最大的x。在区间初始化时,只需用最大的数INF(>MAXl)作为右边界即可:
l= 0
r = INF
现在的问题是是否可以高效的判断C(x),则由于长度为L1的绳子最多切出(L1/x)段长度为x的绳子,因此:
####C(x) = (L1/x) 的总和是否大于等于K。
该种方式的时间复杂度应该是O(N)我是菜鸡如果想的不对希望大佬指正
该题的核心代码应该是 如何判断是否继续二分,既假定一个解并判断是否可行`sum2 = 0;
返回值为bool类型
for (int i = 0;i < n;i++)
{
sum2 = sum2 + b[i] / t;
}
return sum2 < k;`
sum2 在该函数前要初始化,每次调用该函数要保证sum2的值为0.
下面贴AC代码
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<queue>
#include<stack>
#include<cmath>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<cctype>
using namespace std;
#define N 10000
double a[N];
long long b[N];
long long n, k, l;
long long sum, r, sum2, ans, mid;
bool j(int t)
{
sum2 = 0;
for (int i = 0;i < n;i++)
{
sum2 = sum2 + b[i] / t;
}
return sum2 < k;
}
int main()
{
cin >> n >> k;;
for (int i = 0;i < n;i++) {
int temp;
cin >> a[i];
b[i] = a[i] * 100;//因为小数精度不好搞所以乘100转换为整数
sum = sum + b[i];
}
r = sum / k + 1;
while (l < r)
{
mid = (l + r + 1) / 2;//期中二分时(l+r)必须加一不然会爆
if (mid == 0)
break;
if (j(mid))
{
r = mid - 1;//这右界也要减一
}
else
{
l = mid;
}
}
printf("%.2lf", l * 1.00 / 100);//最后在除100转化回来
//并保留两位小数
}