1. 程式人生 > 實用技巧 >Codeforces Round #683 (Div. 2, by Meet IT)C. Knapsack(貪心+思維)

Codeforces Round #683 (Div. 2, by Meet IT)C. Knapsack(貪心+思維)

題意

給你一個上界\(W\)和一系列權值\(w_i\),讓你找到權值中任意一個或多個的和滿足\((W + 1) / 2\leq sum \leq W\)

思路

從大到小貪心。

證明:

​ 假設我貪到了一個這個數本身是滿足\((W + 1) / 2\leq sum \leq W\)那麼我可以直接輸出。

​ 假設所有的權值都是不滿足\((W + 1) / 2\leq sum \leq W\),那麼任意兩個的和都是小於\(W\)的,那麼當他們加起來和大於\((W + 1) / 2\)時輸出就行,否則就是\(-1\)

#include<bits/stdc++.h>
 
using namespace std;
 
#define int long long
const int maxn = 2e5 + 10;
struct NODE {
    int id, val;
    NODE(){}
    NODE(int _id, int _val): id(_id), val(_val){}
    bool operator < (const NODE& x) const {
        return val > x.val;
    }
} a[maxn];
 
 
void solve() {
    int n, W;
    cin >> n >> W;
    int l = (W + 1) / 2, r = W;
    vector<int>ans;
    for (int i = 1; i <=n; ++i) {
        cin >> a[i].val;
        a[i].id = i;
    }
    sort(a + 1, a + 1 + n);
    int sum = 0;
    for (int i = 1; i <= n; ++i) {
        if(a[i].val > r) continue;
        ans.push_back(a[i].id);
        sum += a[i].val;
        if (sum >= l && sum <= r) {
            cout << ans.size() << "\n";
            for (int i = 0; i < ans.size(); ++i) {
                if (i) cout << " ";
                cout << ans[i];
            }
            cout << endl;
            return ;
        }
    }
    cout << -1 << "\n";
}
 
signed main() {
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
}