CodeForces - Problem 1446 - Knapsack - 思维
Posted popodynasty
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeForces - Problem 1446 - Knapsack - 思维相关的知识,希望对你有一定的参考价值。
CodeForces - Problem 1446 - Knapsack - 思维
对于所有物品按照重量从小到大排序,然后从后向前遍历:
- 对于重量已经超过了(omega)的物品,将其忽略掉;
- 对于重量处于([lceil frac{omega}{2} ceil,omega])的物品(如果存在),则直接选取这个物品,输出答案
- 对于所有重量小于(lceil frac{omega}{2} ceil)的物品,从大到小取物品,直到取完.如果中途发现累计重量处于([lceil frac{omega}{2} ceil,omega]),输出答案; 如果取完时重量仍小于(lceil frac{omega}{2} ceil),输出不存在.
本题思维主要在于第三条: 当我们从所有重量处在([lceil frac{omega}{2} ceil,omega])的物品中挑选时:先去重量最大的物品,其重量处于((0,lceil frac{omega}{2} ceil)),接下来再取次大的,由于两个物品重量都处于((0,lceil frac{omega}{2} ceil)),因此重量和不会超过(omega); 此时判断累计重量是否处于([lceil frac{omega}{2} ceil,omega]),如果仍然不是,说明累计重量处于((0,lceil frac{omega}{2} ceil)),那么再取第三个物品后累计重量仍然不会超过(omega),这样以此类推,我们优先选择重量大的,所得到的累计重量就会尽可能地大而又不超过(omega),这样做显然符合题意;
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 2e5+5;
struct node{
ll v;
int p;
};
node a[N];
int ans[N]; int len;
bool comp(const node&a,const node&b){
return a.v < b.v;
}
int find_begin(int n,ll w){
int l = 1, r = n;
while(l < r){
int mid = l+r>>1;
if(a[mid].v >= w){
r = mid;
}else{
l = mid+1;
}
}
return l;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
len=0;
int n;
ll w;
scanf("%d%lld",&n,&w);
for(int i = 1; i <= n; i++){
scanf("%lld",&a[i].v);
a[i].p = i;
}
sort(a+1,a+1+n,comp);
int p = find_begin(n,(w+1)/2);
int ptr = 0;
if(a[p].v > w){
ptr = p-1;
}else if(a[p].v <= w && a[p].v >= (w+1)/2){
printf("1
%d
",a[p].p);
continue;
}else{
ptr = p;
}
int flag = 0;
ll sum = 0;
for(int i = ptr; i >= 1; i--){
if(sum + a[i].v <= w){
sum += a[i].v;
ans[++len] = a[i].p;
}
if(sum >= (w+1)/2){
flag = 1;
break;
}
}
if(flag){
sort(ans+1,ans+1+len);
int first = 1;
printf("%d
",len);
for(int i = 1; i <= len; i++){
if(first)first=0;else putchar(‘ ‘);
printf("%d",ans[i]);
}
putchar(‘
‘);
}else{
printf("-1
");
}
}
// system("pause");
return 0;
}
以上是关于CodeForces - Problem 1446 - Knapsack - 思维的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #439 (Div. 2) Problem B (Codeforces 869B)
Codeforces Round #439 (Div. 2) Problem A (Codeforces 869A) - 暴力
Minimax Problem CodeForces - 1288D(二分+状态压缩)