首页 > 其他分享 >背包典型例题

背包典型例题

时间:2023-04-16 16:22:42浏览次数:45  
标签:典型 背包 int LL long using 例题 dp

一、01背包

for(int i=V;i>=c[i];--i){
	dp[i]=max(dp[i], dp[i-c[i]]+w[i])
}

hdu3466。这个题要考虑dp的无后效性质,简单来说,就是dp与物品排布有关的时候,我们应该选择最优的那一个。如果单独选择

i,j都没有问题的时候。如果先选i再选j可以做到,反之不可以。那么说明pi+qj < pj + qi =》qi-pi > qj - pj。所以应该按照q-p排序之后在01背包。

#include <bits/stdc++.h>

using namespace std;

using LL = long long;

const int N  = 1e5 + 5;

int n, m;

struct node{
    int x, y, z;
    bool operator<(const node& a1)const{
        return y-x < a1.y-a1.x;
    }
};

node a[N];

int dp[1005];

int main(){
    while(cin >> n >> m){
        memset(dp, 0, sizeof(dp));
        for(int i=1;i<=n;++i){
            cin >> a[i].x >> a[i].y >> a[i].z;
        }
        sort(a+1, a+n+1);
        for(int i=1;i<=n;++i){
            for(int j=m;j>=a[i].y;--j){
                dp[j]=max(dp[j], dp[j-a[i].x]+a[i].z);
            }
        }

        int ans=0;
        for(int i=0;i<=m;++i){
            ans=max(ans,dp[i]);
        }
        cout<<ans<<endl;
    }
    
    return 0;
}

二、完全背包

与01背包的一维写法不同,现在的转移方程是:

for(int j=c[i];j<=V;++j){
	dp[j]=max(d[j],dp[j-c[i]]);
}

https://www.luogu.com.cn/problem/P1853

#include <bits/stdc++.h>

using namespace std;

using LL = long long;

const int N  = 5e4 + 5;

LL n, m, T;

LL a[15][3];

LL dp[N];

int main(){
    cin >> n >> T >> m;
    for(int i=1;i<=m;++i){
        cin >> a[i][0] >> a[i][1];
        a[i][0] /= 1000;
    }

    for(int i=1;i<=T;++i){
        int tmp = n / 1000;
        int o=n;
        for(int j=0;j<=tmp;++j)dp[j]=0;
        for(int j=1;j<=m;++j){
            for(int k=a[j][0];k<=tmp;++k){
                dp[k]=max(dp[k], dp[k-a[j][0]]+a[j][1]);
            }
        }
        for(int k=0;k<=tmp;++k)n=max(n, o+dp[k]);
    }

    cout<<n<<endl;
    
    return 0;
}

三、多重背包

http://101.43.147.120/p/P1025

跟01背包一样,但是需要枚举一下第i类需要多少个。

#include <bits/stdc++.h>

using namespace std;

using LL = long long;

const int N  = 1e5 + 5;

int n, m, T;

int a[N][3];

int dp[1005];

int main(){
    cin >> n >> m >> T;

    for(int i=1;i<=n;++i){
        cin >> a[i][0] >> a[i][1] >> a[i][2];
    }

    for(int i=1;i<=n;++i){
        a[i][2] = T / a[i][2]; 
    }

    for(int i=1;i<=n;++i){
        for(int j=m;j>=a[i][1];--j){
            for(int k=1;k<=a[i][2];++k){
                if(j<k*a[i][1])continue;
                else{
                    dp[j]=max(dp[j], dp[j-k*a[i][1]] + k * a[i][0]);
                }
            }
        }
    }

    int ans=0;
    for(int i=0;i<=m;++i)ans=max(ans,dp[i]);
    cout<<ans<<endl;
    
    return 0;
}

此外,还有需要二进制优化的多重背包。其核心思想就是在将多重背包的件数约束转化为一系列二进制表示。例如上述的题目我可以这么写。结果就是会跑到快很多。

#include <bits/stdc++.h>

using namespace std;

using LL = long long;

const int N  = 1e5 + 5;

int n, m, T;

LL a[N][3];

LL dp[1005];

int main(){
    cin >> n >> m >> T;

    for(int i=1;i<=n;++i){
        cin >> a[i][0] >> a[i][1] >> a[i][2];
    }

    for(int i=1;i<=n;++i){
        a[i][2] = T / a[i][2]; 
    }

    for(int i=1;i<=n;++i){
        for(int s=1;s<=a[i][2];s<<=1){
            for(int j=m;j>=s*a[i][1];--j){
                dp[j]=max(dp[j], dp[j-s*a[i][1]] + s * a[i][0]); 
            }
            a[i][2]-=s;
        }
        if(a[i][2]>0){
            for(int j=m;j>=a[i][2]*a[i][1];--j){
                dp[j]=max(dp[j], dp[j-a[i][2]*a[i][1]] + a[i][2]*a[i][0]);
            }
        }
    }
    

    LL ans=0;
    for(int i=0;i<=m;++i)ans=max(ans,dp[i]);
    cout<<ans<<endl;
    
    return 0;
}

标签:典型,背包,int,LL,long,using,例题,dp
From: https://www.cnblogs.com/JohnRan/p/17323475.html

相关文章

  • 多重背包单调队列
    考虑思考完全背包问题的过程。完全背包其实是一个前缀最值的过程。而完全背包就是滑动窗口问题。可以把余数相同的归为一类,然后就可以直接单调队列了,队长\(s\)。#include<cstdio>#definemax(x,y)((x)>(y)?(x):(y))constintN=20001;intn,m,f[N],g[N],q[N];intmain(){......
  • [每天例题]蓝桥杯 C语言 饮料换购
    饮料换购题目    题目要求凭3个瓶盖可以再换一瓶C型饮料,并且可以一直循环下去(但不允许暂借或赊账)。思路分析1.先进行一次if判断,不满足三瓶则直接输出2.满三瓶换一次,但是需要将原来的再加上换购的,然后不断循环,直到再次不符合三瓶。代码#include<stdio.h>i......
  • 第三章部分例题(2)
    例3-4寻找并输出11~999的数m,它满足m、m的平方,和m的三次放均为回文数。分析:判断一个数是否为回文数,可以用除以10取余的方法,从最低位开始,依次取出该数的各位数字,然后用最低位充当最高位,判断是否相等。代码:#include<iostream>usingnamespacestd;boolhuiwen(unsignedn){......
  • 背包DP
    背包DP二进制分组优化考虑优化。我们仍考虑把多重背包转化成0-1背包模型来求解。预处理物品数量是2的次方。且要覆盖物品数量的点。即2n次方+1到kindex=0;for(inti=1;i<=m;i++){intc=1,p,h,k;cin>>p>>h>>k;while(k>c){k-=c;......
  • 第三章部分例题
    例3-1编写一个求x的n次方的函数分析:用数学函数pow求代码部分:#include<iostream>#include<math.h>usingnamespacestd;intmain(){intk,f,l;cin>>k;cin>>f;l=pow(k,f);cout<<l;return0;}例3-2输入一个8位二进制数,将其转换为......
  • C++第三章课本例题
    游戏规则是:每个骰子有6面,点数分别为1、2、3、4、5、6。游戏者在程序开始时输入个无符号整数,作为产生随机数的种子。每轮投两次骰子,第一轮如果和数为7或11则为胜,游戏结束;和数为2、3或12则为负,游戏结束;和数为其他值则将此值作为自己的原数,继续第二轮、第三轮……直到某轮的和数等于......
  • [每天例题]日期之间隔几天
    日期之间隔几天题目 题目要求1.编写一个程序来计算两个日期之间隔了多少天。日期以字符串形式给出,格式为 YYYY-MM-DD2.给定的日期是 1971 年到 2100 年之间的有效日期。3.日期以字符串形式给出。思路分析1.可以将两个日期同时计算他们距离1971年1月1日有多少天,再......
  • 典型案例分享:基于企业级的遥感监测水域现状分析系统
    传统的水质监测具有精度高、时效性高等优点,但是难以从长时间序列、全空间角度了解水质的变化趋势及其成因。随着遥感技术的发展,对水体环境进行区域性、整体性研究的方法趋于成熟。遥感监测水域现状分析系统是基于卫星遥感和IT技术研制了的企业级遥感应用系统,为日常的水环境综合......
  • 背包问题
    01背包问题题目有一个背包的容积为\(m\),有\(n\)个物品,每个物品的体积为\(w\),权重为\(v\),每个物品只能取\(1\)次放入背包中,背包所有物品权重和最大是多少?求值创建一个状态矩阵\(dp\),横坐标\(i\)表示物品编号,纵坐标\(j\)表示背包容量。\(dp[i][j]\)表示在已用背包容量为\(j\)的......
  • HDU 1864最大报销额(一维背包)
    题目地址:HDU1864刚上来看着挺麻烦的。。仔细看了看原来好简单好简单。。。只要去掉一些不符合要求的发票,剩下的就是最简单的背包问题了。。对于小数问题,只要*100就变成整数了。代码如下:#include<algorithm>#include<iostream>#include<cstring>#include<cstdlib>#include......