uva 714 Copying Books(二分法求最大值最小化)
阿新 • • 發佈:2019-02-16
題目大意:將一個個數為n的序列分割成m份,要求這m份中的每份中值(該份中的元素和)最大值最小, 輸出切割方式,有多種情況輸出使得越前面越小的情況。
解題思路:二分法求解f(x), f(x) < 0 說明不能滿足, f(x) >= 0說明可以滿足,f(x) 就是當前最大值為x的情況最少需要劃分多少份-要求份數(如果f(x ) >= 0 說明符合要求而且還過於滿足,即x還可以更小)。
注意用long long .
#include <stdio.h> #include <string.h> int max(const int &a, const int &b) { return a > b ? a : b;} const int N = 1005; int n, T; long long num[N], sum[N], rec[N]; bool judge(int Max) { int cnt = 0, first = 0, end = 1; while (end <= n) { if (sum[end] - sum[first] > Max) { cnt++; first = end - 1; } end++; } return cnt <= T - 1; } int main () { long long cas, lift, right, cur; scanf("%lld", &cas); while (cas--) { // Init; memset(num, 0, sizeof(num)); memset(sum, 0, sizeof(sum)); memset(rec, 0, sizeof(rec)); lift = right = 0; // Read. scanf("%d%d", &n, &T); for (int i = 1; i <= n; i++) { scanf("%lld", &num[i]); sum[i] = sum[i - 1] + num[i]; lift = max(lift, num[i]); } right = sum[n]; // Count; while (lift != right) { cur = (right + lift) / 2; if (judge(cur)) { right = cur; } else lift = cur + 1; } // Draw; long long now = 0, cnt = 0; for (int i = n; i > 0; i--) { if (now + num[i] > lift || i < T - cnt) { rec[i] = 1; cnt++; now = num[i]; } else now += num[i]; } // Printf; for (int i = 1; i < n; i++) { printf("%lld ", num[i]); if (rec[i]) printf("/ "); } printf("%lld\n", num[n]); } return 0; }