背包2讲(2.6)

问题1:装箱问题

题解:这题其实本质上也是01背包,只不过算是变式,要求剩余空间最小值,我们可以转换成最大可以装多少的问题,然后就可以很快的写出题的答案

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int v,n;
int w[50];
int dp[20005];
int main()
{
    scanf("%d%d",&v,&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d",&w[i]);
    }
    for(int i=0;i<n;i++)
    {
        for(int j=v;j>=w[i];j--)
        {
            dp[j]=max(dp[j],dp[j-w[i]]+w[i]);
        }
    }
    printf("%d",v-dp[v]);
    return 0;
}

问题2:开心的金明

题解:和第一道题一样都属于01背包只不过是一个变式,因此我们还是可以找出其中的关系式

dp[j]=max(dp[j],dp[j-v[i]]+v[i]*w[i]) (i代表第i个物品,j代表钱数为j)

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int n,w1;
int w[30];
int v[30];
int dp[30005];

int main()
{
    scanf("%d%d",&w1,&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d%d",&w[i],&v[i]);
    }
    for(int i=0;i<n;i++)
    {
        for(int j=w1;j>=w[i];j--)
        {
            dp[j]=max(dp[j],dp[j-w[i]]+w[i]*v[i]);
        }
    }
    printf("%d",dp[w1]);
    return 0;
}

问题3:小A点菜

题解:这题也是很有意思昂,和平常的01背包终于换了个考法了,但仔细思索发现还是那样,所以难度也不是很大,但是需要找到相应的递推关系式dp[j]=dp[j]+dp[j-v[i]];

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
int n,m;
int v[105];
int dp[10005];

int main()
{
    int flag=0x3f3f3f3f;
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)
    {
        scanf("%d",&v[i]);
        if(v[i]<flag)
            flag=v[i];
    }
    dp[0]=1;
    for(int i=0;i<n;i++)
    {
        for(int j=m;j>=v[i];j--)
        {
            dp[j]=dp[j]+dp[j-v[i]];
        }
    }
    printf("%d",dp[m]);
    return 0;
}

问题4:精卫填海

题解:典型的01背包变式,但是我们需要额外设置一个变量,用于更新最小消耗的体力

只要满足了k(要求的填平所需要的最小体积)就可以更新

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int v,n,c;
int k[10005];
int m[10005];
int dp[10005];
int main()
{
    scanf("%d%d%d",&v,&n,&c);
    for(int i=0;i<n;i++)
    {
        scanf("%d%d",&k[i],&m[i]);
    }
    int sum=-1;
    for(int i=0;i<n;i++)
    {
        for(int j=c;j>=m[i];j--)
        {
            dp[j]=max(dp[j],dp[j-m[i]]+k[i]);
            if(dp[j]>=v)
            {
                sum=max(sum,c-j);
            }

        }
    }
    if(sum==-1)
    {
        printf("Impossible");
    }
    else
        printf("%d",sum);
    return 0;
}

问题5:Bessie's Weight Problem G

题解,很简单和第1,2题都是一个模版没啥可说的

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

int h,n;
int w[505];
int dp[45005];
int main()
{
    scanf("%d%d",&h,&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d",&w[i]);
    }
    for(int i=0;i<n;i++)
    {
        for(int j=h;j>=w[i];j--)
        {
            dp[j]=max(dp[j],dp[j-w[i]]+w[i]);
        }
    }
    printf("%d",dp[h]);
    return 0;
}

问题6:Hay For Sale S

题解:很简单的01背包问题,没什么过多解释,找出关系式就好

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int w,n;
int v[5005];
int dp[50005];
int main()
{
    scanf("%d%d",&w,&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d",&v[i]);
    }
    for(int i=0;i<n;i++)
    {
        for(int j=w;j>=v[i];j--)
        {
            dp[j]=max(dp[j],dp[j-v[i]]+v[i]);
        }
    }
    printf("%d",dp[w]);
    return 0;
}

总结

做这种动态规划问题,一定要有一个思路,那就是去找动规五部曲

1.明白dp数组含义

2.找到dp关系式

3.给dp数组赋初值

4.遍历顺序

5.打印数组,检查错误

相关推荐
小码农<^_^>36 分钟前
优选算法精品课--滑动窗口算法(一)
算法
羊小猪~~38 分钟前
神经网络基础--什么是正向传播??什么是方向传播??
人工智能·pytorch·python·深度学习·神经网络·算法·机器学习
软工菜鸡1 小时前
预训练语言模型BERT——PaddleNLP中的预训练模型
大数据·人工智能·深度学习·算法·语言模型·自然语言处理·bert
南宫生1 小时前
贪心算法习题其三【力扣】【算法学习day.20】
java·数据结构·学习·算法·leetcode·贪心算法
AI视觉网奇2 小时前
sklearn 安装使用笔记
人工智能·算法·sklearn
JingHongB2 小时前
代码随想录算法训练营Day55 | 图论理论基础、深度优先搜索理论基础、卡玛网 98.所有可达路径、797. 所有可能的路径、广度优先搜索理论基础
算法·深度优先·图论
weixin_432702262 小时前
代码随想录算法训练营第五十五天|图论理论基础
数据结构·python·算法·深度优先·图论
小冉在学习2 小时前
day52 图论章节刷题Part04(110.字符串接龙、105.有向图的完全可达性、106.岛屿的周长 )
算法·深度优先·图论
Repeat7152 小时前
图论基础--孤岛系列
算法·深度优先·广度优先·图论基础
小冉在学习2 小时前
day53 图论章节刷题Part05(并查集理论基础、寻找存在的路径)
java·算法·图论