Codeforces Beta Round #3——B. Lorry

本文介绍了一种解决特定背包问题的优化算法,通过价值优先策略选取物品,并针对剩余空间提出两种解决方案,最终输出最大价值及选中物品的序号。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:

现在告诉你有n个物品,背包的体积为V。

然后n行,有两种类型的物品,如果是1类型的物品,那么它的体积为1,如果是2类型的物品,那么它的体积为2。并同时告诉了我们每种物品的价值。

问你在不超过背包的容量的情况下,所能获得的背包的最大价值。并同时输出被选在背包中的物品的序号。

思路:

因为V十分大,所以肯定不能是01背包。

于是我们对每种物品的价值排序,然后优先选择价值高的。

然后有一个点我没考虑到,如果这样优先选择价值高的话,背包的体积可能会有所空出来,但是可以得之背包中空出来的体积肯定是1。

于是就分了两种情况:

1)在后面的物品中选择体积为1的加进去

2)在前面的物品中选择体积为1的删除,并在后面选择体积为2的加入到我们所选的集合中。

最后就是一个WA点,这题中还存在不合法的情况,我觉得就是那个卡了我好久的test21。。。所以我们应该初始化xx为-1,然后判断一下。

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
#define maxn 100010
int vis[maxn],num[maxn];
struct node{
    int t,p;
    double val;
    int idx,v;
}a[maxn];
bool cmp(node a,node b){
    return a.val>b.val;
}
int main(){
    int n,V;
    scanf("%d%d",&n,&V);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&a[i].t,&a[i].p);
        if(a[i].t==1) a[i].val=a[i].p/1.0,a[i].v=1;
        else a[i].val=a[i].p/2.0,a[i].v=2;
        a[i].idx=i;
    }
    sort(a+1,a+1+n,cmp);
    int res=0,ans=0,xx=-1;
    for(int i=1;i<=n;i++){
        if(res+a[i].v<=V){
            res+=a[i].v;
            ans+=a[i].p;
            vis[i]=1;
        }
        else{
            xx=i;
            break;
        }
    }
    //printf("%d\n",ans);
    if(V-res>0&&xx!=-1){        //注意有一种特殊情况,当没有一种物品可以被选进去的时候,也要判断过此时的情况,即为xx!=-1 
        int ans1=ans,a1=0;
        for(int i=xx;i<=n;i++){
            if(a[i].t==1){
                ans1=ans+a[i].p;
                a1=i;
                break;
            }
        }
        int del=0,ans2=0,a2=0;
        for(int i=xx-1;i>=1;i--){
            if(a[i].t==1){
                del=i;
                ans2=ans-a[i].p;
                bool ff=false;
                for(int j=i+1;j<=n;j++){
                    if(a[j].t==2&&!vis[j]){
                        ans2+=a[j].p;
                        a2=j;
                        ff=true;
                        break;
                    }
                }
                if(ff) break;
            }
        }
        if(ans1>=ans2&&ans1>ans){
            ans=ans1;
            vis[a1]=1;
        }
        else if(ans2>=ans1&&ans2>ans){
            ans=ans2;
            vis[del]=0;
            vis[a2]=1;
        }
    }
    printf("%d\n",ans);
    int t=0;
    for(int i=1;i<=n;i++){
        if(vis[i]){
            num[t++]=a[i].idx;
        }
    }
    for(int i=0;i<t;i++){
        printf("%d%c",num[i],i==t-1?'\n':' ');
    }
}
/*
6 4
1 10
1 9
2 8
2 7
1 5
1 4
*/




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值