題解 CF1446A 【Knapsack】
阿新 • • 發佈:2020-11-22
題目大意
給你 \(n\) 個物體,體積為 \(w_i\) 。並且給你一個大小為 \(c\) 的揹包。
要求你取若干個物品使得 : \(\lceil \frac{c}{2} \rceil \le \sum{w_i} \le c\)
並且輸出取了哪些。
題解
考慮貪心。
排序後從大往小的地方去取。
如果當前取了會超過 \(c\) 就不取。
只要大於 \(\lceil \frac{c}{2} \rceil\) 就直接 \(break\)
這麼證明這種做法是正確的?
我們只要找到一種滿足條件的,他沒要求總和最多,也沒要求取的數最多。
所以你只要先去最大的,如果當前取了超過 \(c\) ,那麼他就不能取。
就繼續取小的,這樣是沒有後效的,因為如果你這樣都不可以取,那麼上面的更加不可以取了。
所以你只要從大往小去取,記得記錄編號在排序,因為他要輸出編號。
細節自己讀下程式碼。
程式碼
#include <bits/stdc++.h> using namespace std; #define int long long #define Rep(x, a, b) for(int x = a; x <= b; ++ x) #define Dep(x, a, b) for(int x = a; x >= b; -- x) #define Next(i, x) for(int i = head[x]; i; i = e[i].nxt) int read() { char c = getchar(); int f = 1, x = 0; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); } return x * f; } const int maxn = 200010; int p[maxn]; struct node { int a, id; } e[maxn]; int cmp(node x, node y) { return x.a > y.a; } signed main() { int T = read(); while(T --) { int n = read(), c = read(), cnt = 0, ans = 0, pla = -1; Rep(i, 1, n) e[i].a = read(), e[i].id = i; sort(e + 1, e + n + 1, cmp); Rep(i, 1, n) { ans += e[i].a; if(ans > c) {ans -= e[i].a; continue; } p[++ cnt] = e[i].id; if(ans >= ceil(1.0 * c / 2)) { pla = i; break;} } if(ans >= ceil(1.0 * c / 2) && ans <= c) { printf("%d\n", cnt); Rep(i, 1, cnt) printf("%d ", p[i]); puts(""); } else puts("-1"); } return 0; }