Aggressive cows
http://poj.org/problem?id=2456
题目大意为给一条直线上的n个点,让你随意选取c个点,然后使得这c个点两两之间的最小距离最大,如何选取这c个点使这个最小距离最大,输出最大的最小距离max。
思路
先把坐标排序,之后界定二分的范围,二分的缩小范围的条件则为当两点距离大于所输入的点时,s++,返回s。如若s大于所处的点,说明值太小,将左界变为mid+1,反之将右界赋值为mid-1;当左界与右界之差小于1的时候跳出循环,输出。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int mini(int x,int a[],int n)
{
int p=a[0];
int s=1;
int i;
for(i=1;i<n;i++)
{
if(a[i]-p>=x)
{
s++;
p=a[i];
}
}
return(s);
}
int comp(const void*a,const void*b)
{
return *(int*)a-*(int*)b;
}
int main()
{
int n,c;
int a[100100];
int left,right;
while(scanf("%d%d",&n,&c)!=EOF)
{
int i;
for(i=0;i<n;i++)
scanf("%d",&a[i]);
qsort(a,n,sizeof(int),comp);
left=0;
right=a[n-1]-a[0];
while(right>=left)
{
int mid=(left+right)/2;
if(mini(mid,a,n)>=c)
left=mid+1;
else
right=mid-1;
}
printf("%d\n",left-1);
}
return 0;
}
River Hopscotch
http://poj.org/problem?id=3258
题意是给了n个石头,给了它们到起点的距离,还有一个终点。问要去掉这n个石头中的m个,使得其间距的最小值最大。
思路
这题放在这里是因为和第一题类似。代码只要稍作修改就可以ac。与第一题的区别在于,放多少头牛变为了减去后石头所剩,但因为收尾不能动,所以需要有n-m+2个。其他过程相似,在做的时候有个小疑问,就是如何确保首尾一定放着牛,但后来发现是杞人忧天。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int mini(int x,int a[],int n)
{
int p=0;
int s=0;
int i;
for(i=0;i<=n;i++)
{
if(a[i]-p>=x)
{
s++;
p=a[i];
}
// if(s>n-m)
// return 1;
}
return s;
}
int comp(const void*a,const void*b)
{
return *(int*)a-*(int*)b;
}
int main()
{
int L,N,M;
int a[50100];
int left,right;
while(scanf("%d%d%d",&L,&N,&M)!=EOF)
{
int i;
for(i=0;i<N;i++)
scanf("%d",&a[i]);
a[N]=L;
qsort(a,N+1,sizeof(int),comp);
left=0;
right=L;
while(right>=left)
{
int mid=(left+right)/2;
if(mini(mid,a,N)>=N-M+1)
left=mid+1;
else
right=mid-1;
}
printf("%d\n",left-1);
}
return 0;
}
Drying
http://poj.org/problem?id=3104
题意:有一些衣服,每件衣服有一定水量,有一个烘干机,每次可以烘一件衣服,每分钟可以烘掉k。每件衣服没分钟可以自动蒸发掉一滴水,用烘干机烘衣服时不蒸发。问最少需要多少时间能烘干所有的衣服。
思路
这里进行的二分是对时间的二分,寻找一个最小时间。先设定边界,再取中间值。当中间值的时间大于烘干所用的时间时,说明时间短,对left边界取mid+1,相反,则说明时间还有缩减的可能,将right取mid-1,当left>right时跳出。
#include<stdio.h>
int judge(long long mid,long long a[],long long k,long long n)
{
long long time=0;
long long i;
for(i=0;i<n;i++)
{
if(a[i]<=mid)
continue;
else
{
time+=(a[i]-mid+k-2)/(k-1);//(k-2)/(k-1) 为了获得类似0.999
if(time>mid)
return 0;
}
}
return 1;
}
int main()
{
int N;
long long k;
while(scanf("%d",&N)!=EOF)
{
long long a[100010];
long long k;
long i;
long long max=0;
long long l,r;
for(i=0;i<N;i++)
{
scanf("%lld",&a[i]);
if(a[i]>max)
{
max=a[i];
}
}
scanf("%lld",&k);
l=0;
r=max;
if(k==1)
{
printf("%d\n",max);
break;
}
else
{
long long mid;
while(r-l>1)
{
mid=(r+l)/2;
if(judge(mid,a,k,N))
{
r=mid;
}
else l=mid;
//printf("%d\n",r);
}
}
printf("%d\n",r);
}
return 0;
}
Expanding Rods
题意 有一根绳子的长度为l,在有温度的情况下会变形为一个圆弧,长度为 l1 = (n*c+1)*l;求图中的h;并说明增加的长度不超过原长度的一半。
思路
数学问题,找到公式后用二分法确定精度。
#include<stdio.h>
#include<math.h>
const double esp=1e-8;
int main()
{
double l,n,c,s;
double r;
int T;
int i;
while(scanf("%d",&T)!=EOF)
{
for(i=1;i<=T;i++)
{
scanf("%lf%lf%lf",&l,&n,&c);
if(l<0&&n<0&&c<0)
{
break;
}
if(l==0||n==0||c==0)
{
printf("Case %d: 0\n",i);
continue;
}
double low=0.0;
double high=0.5*l;
double mid;
s=(1+n*c)*l;
while(high-low>esp)
{
mid=(low+high)/2;
r=(4*mid*mid+l*l)/(8*mid);
if( 2*r*asin(l/(2*r)) < s )
low=mid;
else
high=mid;
}
printf("Case %d: %.7lf\n",i,mid);
}
}
return 0;
}