DP 01背包问题

蒟蒻水的第一发博客,被一个模板题折磨了一下午(笑)

洛谷  P1060

代码如下:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int chengji[100000000], jiage[30], jiazhi[30];
int n, m;//n为钱数,m为个数 
int main(void){
cin>>n>>m;
for(int i=0; i<m; i++){
cin>>jiage[i]>>jiazhi[i];
jiazhi[i]=jiage[i]*jiazhi[i];
}
for(int i=0; i<m; i++){
for(int j=n; j>=jiage[i]; j--){
chengji[j]=max(chengji[j],chengji[j-jiage[i]]+jiazhi[i]);
}
}
cout<<chengji[n];
return 0;
}

此为优化后的一维数组,为方便理解,再贴一份二维数组(来自洛谷题解)

#include <iostream>

using namespace std;

int f[30][100000];
int w[10000];
int v[10000];

int main()
{
    int n,m;
    int i,j,k;
    cin>>m>>n;
    //提前相乘
    for(i=1;i<=n;i++)
    {
        cin>>w[i]>>v[i];
        v[i]*=w[i];
    }
    for(int i=1;i<=n;i++)
    {
    //01背包最关键的位置,为防止反复加同一物品,需要倒着搜,这也是01背包与完全背包的不同之处
        for(int c=0;c<=m;c++)
        {
            f[i][c]=f[i-1][c];
            if(c>=w[i])
            f[i][c]=max(f[i][c],f[i-1][c-w[i]]+v[i]);
        }
    }
    cout<<f[n][m];
    return 0;
}

一维数组和二维数组两种思路均为当最后一个物品序号位i时(1<=i<=m)如何能使乘积取最大值,不同点在于起始点的不同。

二维数组的思路为在以序号为i的物体为最后一个时,计算剩余体积为j(0<=j<=n)时能取到的最大乘积,

一维数组的思路为假定将第i个物品放入背包,剩余如何取能取到最大。

一开始想用递归方法做出,但是找不到限制背包空间的表达式,因此做罢。

立一个2020年的flag,把这道题用递归方法再做一遍XD

猜你喜欢

转载自www.cnblogs.com/XBird/p/12321187.html