poj1064----二分的用法!

题意大概说一下:      1:首先给出两个整数n,k,(1<=n<=10000),(1<=k<=10000), 然后给出n个段,要把这n个段切成k个长度相等的小段,要保证这些小段的长度最大!

                                  (二分判断一个解是否可行)

题目链接:https://vjudge.net/problem/POJ-1064

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>  //这个头文件用来开floor 
 6 using namespace std;
 7 int n,k;
 8 double len[10010];
 9 
10 bool judge(double f){
11     int num=0;
12     for(int i=1;i<=n;i++)
13         num+=(int)(len[i]/f);
14     return num>=k;    
15 }
16 
17 int main(){
18     while(scanf("%d%d",&n,&k)!=EOF){
19         for(int i=1;i<=n;i++) scanf("%lf",&len[i]);
20         double lb=0.0,rb=10000000.0; //右端点要开大点,一开始开小了,wa了 
21         for(int i=1;i<=100;i++){ //100次已经够用了,足够小了 
22             double mid=(lb+rb)/2; //枚举中间 
23             if(judge(mid)) lb=mid; //如果比k段多,那么证明这个值取小了,还可以取大点 
24             else rb=mid;
25         }
26         printf("%.2lf\n",(floor(lb*100)/100)); //书上是ub,但是因为足够小,所以lb和ub均可。 
27     }
28     return 0;
29 }
View Code

 刚刚测了 50的版本,

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>  //这个头文件用来开floor 
 6 using namespace std;
 7 int n,k;
 8 double len[10010];
 9 
10 bool judge(double f){
11     int num=0;
12     for(int i=1;i<=n;i++)
13         num+=(int)(len[i]/f);
14     return num>=k;    
15 }
16 
17 int main(){
18     while(scanf("%d%d",&n,&k)!=EOF){
19         for(int i=1;i<=n;i++) scanf("%lf",&len[i]);
20         double lb=0.0,rb=10000000.0; //右端点要开大点,一开始开小了,wa了 
21         for(int i=1;i<=50;i++){ //100次已经够用了,足够小了 
22             double mid=(lb+rb)/2; //枚举中间 
23             if(judge(mid)) lb=mid; //如果比k段多,那么证明这个值取小了,还可以取大点 
24             else rb=mid;
25         }
26         printf("%.2lf\n",(floor(rb*100)/100)); 
27     }
28     return 0;
29 }
View Code

发现左端点会错,右端点是对的,所以还是改成右端点吧

猜你喜欢

转载自www.cnblogs.com/pandaking/p/9835887.html