Poj百练 4131: Charm Bracelet (分类:动态规划)

01背包问题是一道极其经典的线性规划入门问题,这道题也是Poj上的一道经典题目。

直接上代码,转移方程都写在代码里了

这个是我的初始版本,想的比较简单,因为体重要求是3500*13000的大小,如果开这么大一个数组的话大概是180MB,差不多一个红警的大小了,一定会爆

​
//01背包问题
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int main()
{
    int n, m;
    scanf("%d%d",&n, &m);
    int w[n+5], d[n+5];
    for(int i = 1; i <= n; i++)
        scanf("%d%d",&w[i], &d[i]);
    //从前i种物品选择j重量的物品的价值最大值
    int dp[n+5][m+5];
    //因为数组开的比较大所以省去考虑边界情况
    memset(dp, 0, sizeof(dp));
    for(int i = 1; i <= n; i++){
        for(int j= 1; j <= m; j++){
            //状态转移方程
            if(j >= w[i]){
                if(dp[i-1][j] > dp[i-1][j-w[i]]+d[i])
                    dp[i][j] = dp[i-1][j];
                /*else   这是我前期考虑错的一个问题,如果w[i]大于j且还选第i种的话直接就是0了
                    dp[i][j] = dp[i-1][j-w[i]]+d[i];*/
            }
            else
                dp[i][j] = dp[i-1][j];
        }
    }
    printf("%d\n",dp[n][m]);
    return 0;
}

​

然后这是后期采用滚动数组进行优化~由于每个dp至于上一行的垂直对应元素和左面某个元素(j-w[i])有关,所以可以采用从右到左的滚动数组

//01背包问题
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{
    int n, m;
    scanf("%d%d",&n, &m);
    int w[n+5], d[n+5];
    for(int i = 1; i <= n; i++)
        scanf("%d%d",&w[i], &d[i]);
    //从前i种物品选择j重量的物品的价值最大值
    int dp[m+5];
    //因为数组开的比较大所以省去考虑边界情况
    memset(dp, 0, sizeof(dp));
    for(int i = 1; i <= n; i++){
        //采用滚动数组从右到左来求
        for(int j= m; j >= 0; j--){
            //状态转移方程
            if(w[i] <= j)
                dp[j] = max(dp[j], dp[j-w[i]]+d[i]);
        }
    }
    printf("%d\n",dp[m]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/a1097304791/article/details/81539276