2017暑假訓練之二分法
阿新 • • 發佈:2018-12-30
二分法判斷解是否可行
POJ 1064 Cable master
POJ 2456 Aggressive cows
11110000取1
寫掛了無數次check。。。真讓人頭大啊。。
要得到sum > mid, 應該在while內賦值,而要使sum恰好小於,則判斷條件為sum+val > mid。
POJ 2976 Dropping tests
POJ 3579 Median
000011111取1
POJ 1064 Cable master
最大化最小值double a[maxn]; int n, k; bool check(double mid) { int cnt = 0; for (int i = 0; i < n; ++i) cnt += a[i] / mid; return cnt >= k; } int main() { while (scanf("%d%d", &n, &k) == 2) { for (int i = 0; i < n; ++i) scanf("%lf", &a[i]); double l = 0, r = INF; for (int i = 0; i < 100; ++i) { double mid = (l + r) / 2; if (check(mid)) l = mid; else r = mid; } //注意不能四捨五入 printf("%.2lf\n", floor(l * 100) / 100); } return 0; }
POJ 2456 Aggressive cows
11110000取1
POJ 3258 River Hopscotchint x[maxn]; int n, c; bool check(int mid) { int cur = x[0], i = 0, cnt = 1; while (1) { while (i < n && x[i] - cur < mid) ++i; if (i == n) break; cur = x[i++];//每次從選取的下一個開始選擇 ++cnt; } return cnt >= c; } int main() { while (~scanf("%d%d", &n, &c)) { for (int i = 0; i < n; ++i) scanf("%d", &x[i]); sort(x, x + n); int l = 0, r = INF; while (r - l > 1) { int mid = (l + r) >> 1; if (check(mid)) l = mid; else r = mid; } printf("%d\n", l); } return 0; }
寫掛了無數次check。。。真讓人頭大啊。。
要得到sum > mid, 應該在while內賦值,而要使sum恰好小於,則判斷條件為sum+val > mid。
最大化平均值int n, L, m, d[maxn], a[maxn]; bool check(int mid) { int i = 1, sum = d[0], cnt = 0;//保持sum與i差1 while (1) { while (i <= n && sum < mid) { sum += d[i++], cnt++; } if (sum < mid) return false; if (i > n) break; sum = d[i++]; } return cnt <= m; } int main() { while (~scanf("%d%d%d", &L, &n, &m)) { for (int i = 1; i <= n; ++i) scanf("%d", &a[i]); a[0] = 0, a[n+1] = L; sort(a, a + n + 2); int mind = INF; for (int i = 0; i <= n; ++i) { d[i] = a[i+1] - a[i]; mind = min(d[i], mind); } int l = mind, r = L+1; while (r - l > 1) { int mid = (l + r) >> 1; if (check(mid)) l = mid; else r = mid; } printf("%d\n", l); } return 0; }
POJ 2976 Dropping tests
int a[maxn], b[maxn], n, k;
double sum[maxn];
bool check(double mid) {
for (int i = 0; i < n; ++i) sum[i] = (LL)100 * a[i] - b[i] * mid;
sort(sum, sum + n);
double ret = 0;
for (int i = n - 1; i >= k; --i) ret += sum[i];
return ret >= EPS;
}
int main() {
while (scanf("%d%d", &n, &k)) {
if (!n && !k) break;
for (int i = 0; i < n; ++i) scanf("%d", &a[i]);
for (int i = 0; i < n; ++i) scanf("%d", &b[i]);
double l = 0, r = INF;
for (int i = 0; i < 100; ++i) {
double mid = (l + r) / 2;
if (check(mid)) l = mid;
else r = mid;
}
printf("%.0lf\n", l);
}
return 0;
}
查詢第k大的值POJ 3579 Median
000011111取1
int n, m, a[maxn];
bool check(int mid) {
int cnt = 0;
int val;
for (int i = 0; i < n; ++i) {
val = mid + a[i];
if (val > a[n - 1]) break;
cnt += n + (a - upper_bound(a, a + n, val));
}
return cnt <= m;
}
int main() {
while (~scanf("%d", &n)) {
for (int i = 0; i < n; ++i) scanf("%d", &a[i]);
m = (n*(n - 1))>>2;
sort(a, a + n);
int l = 0, r = INF;
while (r - l > 1) {
int mid = (l + r) >> 1;
if (check(mid)) r = mid;
else l = mid;
}
printf("%d\n", r);
}
return 0;
}
這幾天有些怠惰了,振作起來!