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;
}