23.2.8每日总结

今天学习了背包问题,先从01背包问题开始说起吧,01背包问题就是有n件物品,一个容量为v的背包。

 01背包问题作为背包问题中的基础问题,我们解决这类问题的时候最重要的就是求出相对应的状态转移方程,那么如何找出状态转移方程呢,我们可以进行打表的方式来解决这个问题,就是画一个二维数组,然后有i行j列,然后将每个物品的价值和体积放在前面,然后写出每一个情况下该背包的最大价值写在表格中,然后就可以推出它的状态转移方程了就比如这个题的状态转移方程就是d【i】【j】=max(d【i-1】【j】,d【i-1】【j-w【i】】+c【i】)

然后用用二维数组写的话代码如下

#include<bits/stdc++.h>
using namespace std;
int v[1005];   
int w[1005];    
int f[100][100];  

int main() 
{
    int n, m;   
    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 = 1; j <= m; j++)
        {
            if(j < v[i]) 
                f[i][j] = f[i - 1][j];
            else    
                f[i][j] = max(f[i - 1][j], f[i - 1][j - v[i]] + w[i]);
        }           

    cout << f[n][m] << endl;
    return 0;
}

其实是可以在这个基础上进行优化,优化的话就是要从j=m开始进行然后状态转移3方程是就变为

dp【j】=max(d【j】,d【j-w【i】】+c【i】

因为01背包问题的每个数据都是根据上面一行的数据推出来的且是由前推后,所以说j要从m开始

#include<bits/stdc++.h>
using namespace std;
int f[1005];  

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

    for(int i = 1; i <= n; i++) {
        int v, w;
        cin >> v >> w;      
        for(int j = m; j >= v; j--)
            f[j] = max(f[j], f[j - v] + w);
    }

    cout << f[m] << endl;

    return 0;
}

接下来就开始解决完全背包问题,这个问题与01背包问题不同的是每个物品都有无限件可以使用所以说我们就需要要在其代码上进行一些改变朴素的方法就是在上面的二维那个解决方法下在j的for循环里面再添加一个for(int k=0;k+v【i】<=j;k++)就好了然后将其状态转移方程式改写一下就好了

 

#include<iostream>
using namespace std;
int n, m;
int dp[100][100], v[100], w[100];

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++)
                dp[i][j] = max(dp[i][j], dp[i - 1][j - k * v[i]] + k * w[i]);
    cout << dp[n][m] << endl;
return 0;
}

这个其实也是可以优化的这个最后优化出来的状态转移方程式和01背包问题优化出来的方程式是一样的的,但是不同的是完全背包问题是根据同一行的数据推出来的所以里面的j需要从0开始,其实也可以直接从w【i】开始

#include<iostream>
using namespace std;
int f[100];
int v[100],w[100];
int main()
{
    int n,m;
    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 = v[i] ; j<=m ;j++)
    {
            f[j] = max(f[j],f[j-v[i]]+w[i]);
    }
    cout<<f[m]<<endl;
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值