首页 > 编程语言 >DP经典问题----背包问题的代码实现(入门级)(C++/PYTHON)

DP经典问题----背包问题的代码实现(入门级)(C++/PYTHON)

时间:2024-06-12 19:59:42浏览次数:25  
标签:goods PYTHON max C++ ---- int range 背包 input

背包的状态转换方程

i:表示物品序号

j:表示背包大小

W [i]:表示第i件物品的重量

f[i,j]:表示在前i件物品中选择若干件放在承重为 j 的背包中,可以取得的最大价值

f[i-1,j-Wi]:表示在前i-1件物品中选择若干件放在承重为j-Wi的背包中,可以取得的最大价值

Pi(j>=Wi):表示第i件物品的价值,要求背包大小j要大于此件物品的重量

f[i-1,j]:表示前i-1件物品中选择若干件放在承重为j的背包中,可以取得的最大价值

1.01背包问题2. 01背包问题 - AcWing题库

首先我们创立两个一维数组,用来存储大小和价值

再创立一个二维数组用来状态分析

分析背包问题我们是曲线救国,调用已经存在的数据元素来解决问题

物品个数是从1到n,然后分别得出该个数下的最大价值

我们要分析两个状态,放与不放,

第一种--不放i物品:f[i][j]=f[i-1][j](调用的是i-1状态下的最大值)

第二种--放i物品:f[i][j]=f[i-1] [j-v[i]] + w[i](此时同时是调用i-1个物品下的状态,

但是此时放物品那你要留空给这个物品放,so,此时调用的状态转移方程容量是j-v[i]条件下的,

最后再加上w[i]就是该状态下的value了)(当然,背包的容量要大于v[i]要不然放不下i 物品)

last but not least,我们要对两种状态,放与不放的价值大小进行判断

f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i])

最后输出则可。

#include <bits/stdc++.h>
using namespace std;

const int N=1010;
int main(){
    int n,m;
    int v[N],w[N];
    int f[N][N];

    cin>>n>>m;
    for (int i=1;i<=n;i++) cin>>v[i]>>w[i];

    for (int i=1;i<=n;i++)//物品个数 1-n
        for (int j=0;j<=m;j++){//容量  0-m
            f[i][j]=f[i-1][j];//先赋值给不放第i个,在下面再比较放与不妨
            if (j>=v[i]) f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i]);//f[i][j]=  (1) f[i-1][j] (2) f[i-1][j-v[i]]+w[i]
            //第一种情况是取的是i-1个物品的最大 容量为j
            //第二种是[i-1]个但是把第i个放入的情况,那要取的是【i-1】,但是其内存要是j-v[i]--相当于留了一个地方存这个物品,取得是之前的最后再加上w[i]成为新的f[i][j]
        }
    cout<<f[n][m]<<endl;
    return 0;
}
n,m=map(int,input().split())#n是物品,m是容量
v=[]#容量
w=[]#价值
v.append(0)
w.append(0)
f=[[0 for j in range(n+m)] for i in range(m+n)]
for i in range(n):
    a,b=map(int,input().split())
    v.append(a)
    w.append(b)
for i in range(1,n+1):
    for j in range(0,m+1):
        f[i][j]=f[i-1][j]
        if j>=v[i]:
            f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i])
print(f[n][m])

2.完全背包问题3. 完全背包问题 - AcWing题库

#include <bits/stdc++.h>
using namespace std;

const int N=1010;

int v[N],w[N];
int f[N][N];
int n,m;
int main()
{
    cin>>n>>m;
    for (int i=1;i<=n;i++) cin>>v[i]>>w[i];
    for (int i=1;i<=n;i++)
        for (int j=0;j<=m;j++)
            for (int k=0;k*v[i]<=j;k++)
                f[i][j] = max(f[i][j],f[i-1][j-k*v[i]]+k*w[i]);
    cout<<f[n][m]<<endl;
    return 0;
}
n, m = map(int, input().split())
v, w = [0] * (n + 1), [0] * (n + 1)

for i in range(1, n + 1):
    v[i], w[i] = map(int, input().split())

# 二维:
# 状态表示f[i][j] 选择前i个物品,总体积小于等于j的最大价值
# 状态计算f[i][j] = max(f[i-1][j], f[i][j - v[i] + w[i] if j >= v[i])
# 物品种类不限,所以max中第二项和0-1背包不同

f = [[0] * (m + 1) for _ in range(n + 1)]

for i in range(1, n + 1):
    for j in range(m + 1):
        f[i][j] = f[i-1][j]
        if j >= v[i]:
            f[i][j] = max(f[i][j], f[i][j-v[i]] + w[i])

print(max(f[n]))
n, m = map(int, input().split())
v, w = [0] * (n + 1), [0] * (n + 1)

for i in range(1, n + 1):
    v[i], w[i] = map(int, input().split())
# 一维:f[j] 代表总体积小于等于j的最大价值
# 因为每种物品数量不限,所以j从小到大更新,即可以使用前面当前层j更新后的结果

f = [0] * (m + 1)
for i in range(1, n + 1):
    for j in range(v[i], m + 1):
        f[j] = max(f[j], f[j-v[i]] + w[i])
print(f[m])

3.多重背包问题4. 多重背包问题 I - AcWing题库

#include <bits/stdc++.h>

using namespace std;

const int N=110;
int v[N],w[N],s[N];
int f[N][N];

int main()
{
    int n,m;
    cin>>n>>m;
    for (int i=1;i<=n;i++) cin>>v[i]>>w[i]>>s[i];
    for (int i=1;i<=n;i++)
        for (int j=0;j<=m;j++){
            for(int k=0;k<=s[i] && k*v[i]<=j;k++)
            {
                f[i][j]=max(f[i][j],f[i-1][j-k*v[i]]+w[i]*k);
            }
        }
    cout<<f[n][m]<<endl;
    return 0;
}
​
n,v = map(int, input().split())
goods = []
for i in range(n):
    goods.append([int(i) for i in input().split()])

new_goods = []

for i in range(n):
    for j in range(goods[i][2]):
        new_goods.append(goods[i][0:2])

goods = new_goods
n = len(goods)

dp = [0 for i in range(v+1)]

for i in range(n):
    for j in range(v,-1,-1):
        if j>= goods[i][0]:
            dp[j] = max(dp[j], dp[j - goods[i][0]] + goods[i][1])

print(dp[-1])

​

4.数字三角形3304. 数字三角形 - AcWing题库

数字三角形属于线性DP问题。状态表示也是一个2维数组,f[i][j],i,j分别表示行与列

状态分析同时也是f[i][j]调用已经存在的状态值,该题的f[i][j]可以由两个方向过来,左上右上,

左上:f[i-1][j-1]+a[i][j]

右上:f[i-1][j]+a[i][j]

f [i][j]=max ( f [i-1] [j-1] + a[i] [j] , f [i-1] [j] + a[i] [j])

数字三角形题目还需注意左右次数的问题。

#include<iostream>

using namespace std;

const int N = 510 , M = -1e9;;

int n;

int a[N][N];
int f[N][N];

int main(){
    cin >> n;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= i; j++){
            cin >> a[i][j];
        }
    }
    for(int i = 0; i <= n; i++){
        for(int j = 0; j <= i+1; j++){            
        //注意这里的循环判断条件 从零开始到最后一个数字的后一个位置都要初始化,因为他会用到左边界和右边界上的值.
            f[i][j] = M;
        }
    }
    f[1][1] = a[1][1];

    for(int i = 2; i <= n; i++){
    //前面第一个位置只有一种情况,所以从2开始
        for(int j = 1; j <= i; j++){
            f[i][j] = max(f[i-1][j-1]+a[i][j], f[i-1][j]+a[i][j]);
        }
    }
    if (n % 2 == 0) cout << max(f[n][n / 2], f[n][n / 2 + 1]) << '\n';
    else cout << f[n][n / 2 + 1];
    return 0;
}

n=int(input())
arrs=[[0 for i in range(1,n+1+1)] for i in range(n+1)]#存数的数组
arr=[[0 for i in range(1,n+3)] for i in range(n+1)]#动态规划状态调用数组
for i in range(1,n+1):
        arrs[i][1:n]=list(map(int,input().split()))
arr[1][1] =arrs[1][1]
for i in range(2,n+1):
    for j in range(1,i+1):
        arr[i][j]=max(arr[i-1][j-1]+arrs[i][j],arr[i-1][j]+arrs[i][j])

if n % 2 == 1:
    print(arr[-1][n//2 + 1])
else:
    print(max(arr[-1][n//2],arr[-1][n//2+1]))

注:作者一些题目的解法可能并不是最优解,可以就行指出探讨。

标签:goods,PYTHON,max,C++,----,int,range,背包,input
From: https://blog.csdn.net/2302_79847831/article/details/139631735

相关文章

  • 第壹章第14节 C#和TS语言对比-委托事件(仅C#)
    水一篇,因为《函数方法》章节已经说了,但那个章节比较长,知识点又多,可能有人会看不到。委托事件是C#中的一个难点,但我觉得,和TS/JS中的函数表达式放在一起时,委托和事件就变得很简单了。一、从TS的函数表达式说起TS/JS中函数是一等公民,function是一种类型,定义的具体函数是一......
  • 线程安全问题【snychornized 、死锁、线程通信】
    目录一、线程安全1.1线程安全问题?1.2如何解决线程安全问题方法具体如何实现?1.3同步方法1.4同步代码块1.5总结1.6售票例子1.8补充二、线程安全的集合三、死锁【了解】四、线程通信4.1同步方法4.2同步代码块4.3wait和sleep本篇的思维导图最后一、线程......
  • DllPlugin
    什么是DLLDllPlugin和DllReferencePlugin提供了拆分包的方法,可以极大地提高构建时性能。术语DLL代表动态链接库,它最初是由Microsoft引入的。.dll为后缀的文件称为动态链接库,在一个动态链接库中可以包含给其他模块调用的函数和数据把基础模块独立出来打包到单独的动态连接库......
  • Java日期类Date、SimpleDateFormat 日期格式类、Calendar详细介绍
    目录一、Date类1.1Date类简单介绍1.2Date类的构造方法代码演示二、SimpleDateFormat日期格式化类2.1SimpleDateFormat日期格式化类简单介绍2.2构造方法代码演示日期格式化模板常用方法代码演示注意三、Calendar类3.1简单介绍3.2创建对象代码演示3.3静......
  • web安全-前端层面
    参考资料引荐https://blog.csdn.net/hack0919/article/details/130929154XSS简介跨站脚本攻击(Cross-SiteScripting,简称XSS)当用户将恶意代码注入网页时,其他用户在浏览网页时就会受到影响攻击主要方向主要用于盗取cookie凭据,钓鱼攻击,流量指向等攻击类型反射型xss......
  • 【供应链管理】供应链管理降本增效图库,包括流程图、框架图、优化图、供应商管理
    **【供应链管理】供应链管理降本增效图库**一、降本增效流程图此流程图详细展示了供应链管理过程中的降本增效环节。从需求预测、采购计划制定、供应商选择、物料入库、生产排程、物流运输到最终的销售与售后服务,每个环节都通过优化流程、减少浪费、提高效率等措施实现成本......
  • Base64编码解码流程的初步学习
    目录什么是Base64编码?为什么要学习Base64编码?Base64编码基础原理介绍Base64编码组成Base64编码索引表Base64编码规则Base64编码过程简记编码流程实战Base64编码(不同情况举例说明)1.待编码字符数量为3的倍数2.待编码字符数量不为3的倍数Base64解码原理简单介绍Base64解码过程Base6......
  • 【ubuntu】记住gitlab的登录账号密码
    一、场景   当我们拉取多个项目时,每次总要输入密码,http方式的时候  二、方法gitconfig--globalcredential.helperstore然后可以手动配置账号密码配置~/.gitconfig文件[user][email protected][credential]helper=store[f......
  • 模拟epoll的饥饿场景
    说明一直听说epoll的饥饿场景,但是从未在实际环境中面对过,那么能不能模拟出来呢?实际的情况是怎样呢?模拟步骤基于epoll写一个简单的tcpechoserver,将每次read返回的字节数打印出来模拟一个客户端大量写入测试其他客户端能否正常返回Server代码#include<stdio.h>#include......
  • Linux防火墙
    Netfilter是Linux内核中构建防火墙的网络子系统。firewalld是iptables的一个封装,更容易地管理iptables,firewalld和iptables一样,它们的作用都用于维护规则,而真正使用规则干活的是内核的netfilter。firewalld:firewalld是较新的防火墙管理工具,主要在基于RHEL/CentOS7及更高版本的......