[UVA-11100] The Trip
阿新 • • 發佈:2018-11-24
題目大意
大箱子能裝小箱子,求在滿足最少箱子的情況下,最小化每個箱子中最大的箱子個數.
解析
想到二分列舉箱子數,然後貪心的選擇放進箱子的位置.
最優策略一定是將最大的 \(m\) 個先找出來,然後把剩下的放到這 \(m\) 箇中,
我們發現子問題和上述問題是一樣的, 所以貪心策略不變.
只需要判斷這樣貪心出來會不會有違反遞減序列性質的就行了
注意: 一定要每個 case 間輸出空格, 數的末尾不能有多餘空格, 不然會 WA
程式碼
#include <bits/stdc++.h> using namespace std; #define rep(i, s, t) for (int i = (int)(s); i <= (int)(t); ++ i) const int maxn = 1e4 + 10; int a[maxn], n; vector<int> b[maxn]; bool check(int m) { for (int i = 0; i < maxn; ++ i) b[i].clear(); for (int i = 1; i <= m; ++ i) b[i].push_back(a[i]); for (int i = m + 1; i <= n; ++ i) { int next = (i - 1) % m + 1; if (a[i] < *(b[next].end() - 1)) b[next].push_back(a[i]); else return false; } return true; } int main() { while (~scanf("%d", &n) && n) { rep(i, 1, n) scanf("%d", a + i); sort(a + 1, a + n + 1); reverse(a + 1, a + n + 1); int l = 1, r = n, mid; while (l < r) { if (check(mid = (l + r) >> 1)) r = mid; else l = mid + 1; } check(l); printf("%d\n", l); vector<int>::iterator it; for (int i = 1; i <= l; ++ i) { sort(b[i].begin(), b[i].end()); printf("%d", *b[i].begin()); for (it = b[i].begin()+1; it != b[i].end(); ++ it) { printf(" %d", *it); } putchar(10); } putchar(10); } }