题目:题目太长了!
https://vjudge.net/problem/POJ-1064
题意分析:给了你N根长度为小数形式的棍子,再给出了你需要分的棍子的数量K,但要求你这K根棍子的长度必须是一样长的。需要你求解出满足题意的最长可能的棍子长度。根据二分找最大值的应用写即可。
需要注意的是:
1.注意题目给的范围是All cables are at least 1 meter and at most 100 kilometers in length;
2.在写满足条件的函数时,对于int强制转换类型的应用,一定要注意后面的括号;(起初这里WA的)
3.因为是找最大值,所以用right;
4.100次循环的二分写法可以达到2^100,即可以达到10^30,足够了。
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const int MAXN = 1e4+5;
int N, K;
double Data[MAXN];
bool fun(double x)
{
int cnt = 0;
for(int i = 0; i < N; i++)
cnt += (int)(Data[i]/x); //cnt += (int)Data[i]/x; WA
if(cnt >= K)
return true;
else
return false;
}
void solve()
{
double left = 0, right = 100001;
double mid;
for(int i = 0; i < 100; i++)
{
mid = (left+right)/2;
if(fun(mid))
left = mid;
else
right = mid;
}
printf("%.2f
", floor(right*100)/100);
}
int main()
{
while(~scanf("%d %d", &N, &K) )
{
for(int i = 0; i < N; i++)
scanf("%lf", &Data[i]);
solve();
}
return 0;
}
对于第二种二分写法,需要注意的是在用exp的时候,exp不能取太少,同时不要用小的左值去减右值,最好是用一个正值去和exp进行比较判断。
#include <cstdio>
#include <cstring>
#include <cmath>
#define exp 1e-5
using namespace std;
const int MAXN = 1e4+5;
double Data[MAXN];
int N, K;
bool fun(double x)
{
int cnt = 0;
for(int i = 0; i < N; i++)
cnt += (int)(Data[i]/x);
return cnt >= K;
}
void solve()
{
double left = 0, right = 100000, mid;
while(right - left > exp) // **while(left - right < exp)
{
mid = (left + right)/2;
if(fun(mid))
left = mid;
else
right = mid;
}
printf("%.2f", floor(right*100)/100);
}
int main()
{
while(~scanf("%d %d", &N, &K))
{
for(int i = 0; i < N; i++)
{
scanf("%lf", &Data[i]);
}
solve();
}
return 0;
}