dp中的简化背包问题

声明:来自《挑战程序设计竞赛》,经过思考总结。

dp1.cpp

内含问题介绍,解决思路,与源代码

 
/*简化背包问题
有n个重量和价值分别为Wi,Vi的物品。从这些物品中挑选出总重量不超过W的物品,求所有
挑选方案中价值总和的最大值
1<=n<=100
1<=Wi,Vi<=100
1<=W<=10000
*/
//以下为基本的穷竭搜索,考虑所有情况
#include<iostream>
using namespace std;
#include<algorithm>
//输入
int n, W;
int w[1000], v[1000];
//从第i个物品开始挑选总重小于j的部分,使用时i为0,深层递归至解决问题
int rec(int i, int j)
{
	int res;//已挑选价值
	if (i == n )//最后一个物品已挑选完
	{
		res = 0;
	}
	else if (j < w[i])//j为容许重量
	{
		res = rec(i + 1, j);
	}
	else
	{
		//考虑两种情况,挑选i与不挑选i,然后进入rec(i+1)
		res = max(rec(i + 1, j), rec(i+1, j - w[i]) + v[i]);
	}
	return res;
}
void Solve()
{
	cout<<rec(0, W);
}
 
dp2.cpp 记忆化搜索 //在dp1穷竭搜索的基础上进行改进,降低复杂度,使之成为记忆化搜索 #include<algorithm> 
#include<iostream> 
using namespace std; 
int n, W; 
int w[1000], v[1000]; 
int dp[1000][1000]; /*记忆化数组,只用于减小复杂度,防止递归浪费,不能取代res, 因为还需要用到rec[i+1][j]递归,dp[i+1][j]还未赋值*/ 
int rec(int i, int j) 
{ 
    if (dp[i][j] >= 0)//如果计算过dp[i][j],直接返回 
        { return dp[i][j]; } 
    int res; 
    if (i == n) 
        { dp[i][j] = 0; } 
    else if (j < w[i]) 
        { res = rec(i + 1,j); } 
    else 
        { 
            res = max(rec(i + 1,j), rec(i + 1,j - w[i]) + v[i]); 
        } 
    return dp[i][j]=res; 
} 
void solve() 
    { //-1表示尚未计算过,初始化整个数组 
    memset(dp, -1, sizeof(dp)); 
    rec(0, W); } 
/*dp3.cpp 利用递推关系的dp  1.在dp2中,res与dp[i][j]明显出现了赘余,功能大幅度重叠 dp的功能是减小复杂度,局部变量res用于记录已选价值,而dp明显是可以替代res的, 只是在dp2的使用过程中,若将未赋值的dp[i+1]赋值给dp[i]将会出错,所以使用rec进行递归 而将i从n-1向0开始计算便可以解决这个问题。 2.dp数组从全0开始填充,dp[i][j]为根据rec的定义,从第i个物品开始挑选总重小于j的总价值最大值。 3.因为没有递归函数的自动运行,加入j循环 以下为代码*/ 
    #include<algorithm> 
    #include<iostream> 
    using namespace std; 
    int n, W; 
    int w[1000], v[1000]; 
    int dp[1000][1000]; 
    void solve() 
    { memset(dp, 0, sizeof(dp));//虽然默认初始化为全0,为了可重用性,加入初始化操作 
    for (int i = n - 1; i >= 0; i--) 
    { 
        for (int j = 0; j <=W; j++) 
            { if (j < w[i]) 
                    { 
                        dp[i][j] = dp[i + 1][ j]; 
                    } 
              else 
                    { dp[i][j] = max(dp[i + 1][ j], dp[i + 1][ j - w[i]] + v[i]);
         } } }
     cout << dp[0][W]; }
发布了5 篇原创文章 · 获赞 0 · 访问量 6065

猜你喜欢

转载自blog.csdn.net/srplus/article/details/54923590