POJ 3258 \poj 3273\poj 3122 【二分】

时间:2022-09-13 00:01:16
昨天搜水题做,一不小心进一牛人的博客,
看到几道二分题的报告,忍不住做了一下,顺便把人家对题目的描述偷懒过来,说我邪恶吧( ⊙ o ⊙ )!
POJ 3258 River Hopscotch
http://poj.org/problem?id=3258
长为L的河道,起点在0位置,终点为L位置,期间分布着n块石头,石头不会重叠
求拆掉其中的m块石头,使相邻两石头间的距离的最小值最大,并输出这个值。。。
额。。。貌似描述不清。。。将就一下,(*^__^*) 嘻嘻……
POJ 3258 \poj 3273\poj 3122 【二分】POJ 3258 \poj 3273\poj 3122 【二分】View Code
#include < stdio.h >
#include
< string .h >
#include
< algorithm >
using namespace std;
const int N = 50000 + 10 ;
long rocks[N];
long l,n,m;

bool ok( long v)
{
int i;
int remove = 0 ;
int pre = 0 ;
for (i = 1 ;i < n;i ++ )
{
if (rocks[i] - rocks[pre] < v)
{
remove
++ ;
if (remove > m) return false ;
}
else
{
pre
= i;
}
}

return true ;
}
int main()
{


while (scanf( " %ld%ld%ld " , & l, & n, & m) != EOF)
{
int i;
for (i = 1 ;i <= n;i ++ )
scanf(
" %ld " , & rocks[i]);
rocks[
0 ] = 0 ;
rocks[n
+ 1 ] = l;
n
+= 2 ;

sort(rocks,rocks
+ n);

long left = 0 ;
long right = l;
long ans = l;
while (left <= right)
{
long mid = (left + right) >> 1 ;
if (ok(mid))
{
ans
= mid;
left
= mid + 1 ;
}
else
right
= mid - 1 ;
}

printf(
" %ld\n " ,ans);

}
return 0 ;
}
poj 3273 Monthly Expense
题意:给你天数n,和每天需要花的钱,让你把这些天分成m份(每份都是连续的天),
要求每份的和尽量少,输出这个和。
分析:二分时,left取支出最多的那一天的花费,right取总花费即可 
http://poj.org/problem?id=3273
#include < stdio.h >
const int N = 100000 + 10 ;
int day[N];
int n,m;

bool ok(__int64 v)
{
int tm = m;
int i = 0 ;
while (tm > 0 && i < n)
{
__int64 curs
= v - day[i];
if (curs < 0 ) return false ;
i
++ ;
while (i < n && curs >= day[i])
{
curs
-= day[i];
i
++ ;
}
tm
-- ;
}

if (i == n) return true ;
return false ;
}
int main()
{

while (scanf( " %d%d " , & n, & m) != EOF)
{
int i;
__int64 ans;
__int64 sum
= 0 ;
__int64 left
= 0 ;
for (i = 0 ;i < n;i ++ )
{
scanf(
" %d " , & day[i]);
if (day[i] > left)left = day[i];
sum
+= day[i];
}


__int64 right
= sum;
ans
= 0 ;
while (left <= right)
{
__int64 mid
= (left + right) >> 1 ;
if (ok(mid))
{
ans
= mid;
right
= mid - 1 ;
}
else
left
= mid + 1 ;
}

printf(
" %I64d\n " ,ans);

}
return 0 ;
}
poj 3122 Pie

题意是:某人在生日的时候请朋友一起吃pie,但是他的朋友十分挑剔,
如果有人分到了一块比其他人大的pie,那么其他的朋友就会抱怨,因此每个人,
包括主人,都必须分到大小一样的pie,但是每个人的pie只能是从一块大的圆形pie中切出来的,
要求求出每人能分到的最大的pie,给定圆形pie的数量 n,朋友数量m,以及每个pie的半径r
#include < stdio.h >
#include
< algorithm >
using namespace std;
const int N = 10000 + 10 ;
double s[N];
int r[N];
const double pi = 3.141592653589793238462643383279502884197169399 ;
int n,f;

bool ok( double v)
{
int i = n - 1 ;
double tf = f;
while (i >= 0 && tf > 0 )
{
int cur = ( int )(s[i] / v);
tf
-= cur;
i
-- ;
}
if (tf > 0 ) return false ;
return true ;
}
int main()
{
int T,i;
while (scanf( " %d " , & T) != EOF)
{
while (T -- )
{

scanf(
" %d%d " , & n, & f);
f
++ ;
for (i = 0 ;i < n;i ++ )
scanf(
" %d " , & r[i]);

sort(r,r
+ n);
for (i = 0 ;i < n;i ++ )
{
s[i]
= ( double (r[i] * r[i]));
}

double left,right;
right
= s[n - 1 ];
left
= 0 ;
double ans = 0 ;
while ((right - left) >= 0.0000001 ) // 注意精度处理
{
double mid = (left + right) / 2 ;
if (ok(mid))
{
ans
= mid;
left
= mid;
}
else
right
= mid;
}

printf(
" %.3lf\n " ,ans * pi);
}
}
return 0 ;
}