<span>题解 CF1446A 【Knapsack】</span>

题目大意

给你 \(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;
}
全部评论

相关推荐

MingoTree:看不出你你的技术栈,想找什么工作,然后课设项目别写上去了,自我评价删了,前后端你想好你要干啥,这种简历投上去秒挂的
点赞 评论 收藏
分享
01-23 19:12
门头沟学院 Java
榨出爱国基因:你还差 0.1% 就拿到校招礼盒,快叫朋友给你砍一刀吧
投递拼多多集团-PDD等公司6个岗位
点赞 评论 收藏
分享
02-03 10:14
东南大学 Java
求各位大佬帮忙改改简历提提建议
黑皮白袜臭脚体育生:简历条例统一按使用了什么技术实现了什么功能解决了什么问题或提升了什么性能指标来写 可以看我帖子简历话术写法
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务