标签:floor 最大的 int 转化 大小 循环 保留 inf code
二分答案
基本模板
在一个有序数组中二分查找一个值 k
1 // 在一个单调数组里面二分查找某一个值 k 2 int n, k; 3 int a[MAXN]; 4 5 void solve() { 6 int lb = -1, ub = n; 7 while (ub - lb > 1) { 8 int mid = (lb + ub) / 2; 9 if (a[mid] >= k) { 10 ub = mid; 11 } else { 12 lb = mid; 13 } 14 } 15 printf("%d\n", ub); 16 }
例题分析
POJ1064
假定一个解并判断是否可行
题目:有 N 条绳子,长度分别为L。如果从他们中切割出 K 条长度相同的绳子的话,这 K 条绳子每条最长能有多长。答案保留到小数点后两位
解:C(x) = 可以得到 k 条长度为 x 的绳子 = floor((Li / x)的总和是否大于 k )
代码如下:
注意在程序判定中,我们的解的范围要求小数点后两位,因为 1 次循环可以将区间的范围缩小一半,100 次循环则可以达到 10-30 的精度范围。除此之外,也可以把中止条件设为像 (ub - lb)> EPS 这样,指定一个区间的大小
1 int N, K; 2 double L[MAXN]; 3 4 bool C(double x) { 5 int num = 0; 6 for (int i = 0; i < N; i++) { 7 num += (int)(L[i] / x); 8 } 9 return num >= K; 10 } 11 12 void solve() { 13 // 初始化解的范围 14 double lb = 0, ub = INF * 1.0; 15 16 // 重复循环,直到解的范围足够小 17 for (int i = 0; i < 100; i++) { 18 double mid = (lb + ub) / 2; 19 if (C(mid)) 20 lb = mid; 21 else 22 ub = mid; 23 } 24 printf("%.2f\n", floor(ub * 100) / 100); 25 } 26 27 int main() { 28 #ifndef ONLINE_JUDGE 29 freopen("input.txt", "r", stdin); 30 #endif 31 scanf("%d %d", &N, &K); 32 for (int i = 0; i < N; i++) scanf("%lf", &L[i]); 33 solve(); 34 return 0; 35 }
POJ 2456
最大化最小值
题目:
农夫约翰打了一间有 N 间牛舍的小屋。牛舍排在一条线上,第 i 号牛舍在 x_i 的位置。但是他的 M 头牛对小屋很不满意,因此经常互相攻击。约翰为了防止牛之间的互相伤害,因此决定把每头牛都放在离其他牛尽可能远的牛舍。也就是要最大化最近的两头牛之间的距离。
解:
C(d)= 可以安排牛的位置使得最近的两头牛的距离不小于 d。则问题转化为求最大的 d
贪心:
对牛舍的位置进行排序;
把第一头牛放入 $x_0$ 的牛舍;
如果第 i 头牛放入了 $x_j$ 的话,第 $i+1$ 头牛就要放入满足 $x_j+d<=x_k$ 的最小的 $x_k$ 中
1 int N, M; 2 int x[MAXN]; 3 4 bool C(int d) { 5 int last = 1; 6 for (int i = 1; i < M; i++) { 7 int crt = last + 1; 8 while (crt <= N && x[crt] - x[last] < d) { 9 crt++; 10 } 11 if (crt == N + 1) return false; 12 last = crt; 13 } 14 return true; 15 } 16 17 void solve() { 18 sort(x + 1, x + 1 + N); 19 int lb = 0, ub = INF; 20 while (ub - lb > 1) { 21 int mid = (ub + lb) / 2; 22 if (C(mid)) 23 lb = mid; 24 else 25 ub = mid; 26 } 27 printf("%d\n", lb); 28 } 29 30 int main() { 31 #ifndef ONLINE_JUDGE 32 freopen("input.txt", "r", stdin); 33 #endif 34 scanf("%d %d", &N, &M); 35 for (int i = 1; i <= N; i++) scanf("%d", &x[i]); 36 solve(); 37 return 0; 38 }
标签:floor 最大的 int 转化 大小 循环 保留 inf code
原文地址:https://www.cnblogs.com/romaLzhih/p/11619504.html