1 条题解

  • 0
    @ 2025-8-24 21:56:54

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 违规用户名U56916
    故地重游,还是怀念

    搬运于2025-08-24 21:56:54,当前版本为作者最后更新于2018-04-11 16:49:27,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    莫名其妙找了这道题,然后莫名其妙的做了好几天。

    想看题解发现是个dfs记忆剪枝,不是动规于是自己苦打终于打出来了

    其实这是一道很好的背包题

    费用是一维————————挂钩

    但是我没有敢压缩状态,所以开了二维数组

    f[i][j]表示前i件物品在有j个挂钩的情况下的最大价值

    然后状态转移为f[i][j]=max(f[i-1][j],f[i-1][j-w[i]+1]+v[i])

    这是错的

    因为j-w[i]+1可能是个负数,没有意义,这时候就要考虑这物品直接挂在手机上即j=1,也就需要我们把j-w[i]和0取最大值保证有意义

    所以正解方程为f[i][j]=max(f[i-1][j],f[i-1][max(j-w[i].a,0)+1]+w[i].b);//这里的a是钩子,b是价值

    为什么我用结构体呢?

    并不是我闲的*疼,而是我们要进行一个排序让钩子多的在前面先计算,这个因为把钩子少的先计算很有可能多次挂在手机上没有意义

    然后赋初值

    我们应该把不可能的情况赋成极值即

    for(int i=0;i<=n;i++) f[0][i]=MAXN,f[i][n+1]=MAXN;

    然后f[0][1]=0这是初始状态

    下面贴AC代码

    #include<bits/stdc++.h>//注意万能头比赛不能用
    using namespace std;
    const int MAXN=-1000000000;
    int f[3010][3010];//蒙的数据范围
    struct wu{
        int a,b;
    }w[3010];
    bool cmp(wu i,wu j){
        return i.a>j.a;
    }
    int ans=-2147483647;
    int main(){
        int n;
        cin>>n;
        for(int i=1;i<=n;i++) scanf("%d%d",&w[i].a,&w[i].b);
        sort(w+1,w+1+n,cmp);
        for(int i=0;i<=n;i++) f[0][i]=MAXN,f[i][n+1]=MAXN;
        f[0][1]=0;
        for(int i=1;i<=n;i++){
            for(int j=0;j<=n;j++){
                f[i][j]=max(f[i-1][j],f[i-1][max(j-w[i].a,0)+1]+w[i].b);
            }
        }
        for(int i=0;i<=n;i++) ans=max(ans,f[n][i]);//每个钩子都有可能
        cout<<ans;
        return 0;
    }
    
    • 1

    信息

    ID
    3097
    时间
    1000ms
    内存
    125MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者