01背包问题

                        ***01背包问题***

题意:
有n个重量和价值分别为Wi和Vi的物品。从这些物品中挑选出总重量不超过W的物品,求所有挑选方案中价值总和的最大值。
限制条件:
n在[1,100]之间;
wi和vi在[1,100]之间;
W在[1,10000]之间。
动态规划代码如下:

/*动态规划版的01背包问题*/
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=520;
int dp[maxn][20*maxn];
int w[maxn],v[maxn],W,n;
void solve()
{
    memset(dp,0,sizeof(dp));
    for(int i=0; i<n; i++)
        for(int now=0; now<=W; now++)
            if(now<w[i])//如果不能装下这个物品
                dp[i+1][now]=dp[i][now];
            else
                dp[i+1][now]=max(dp[i][now],dp[i][now-w[i]]+v[i]);
    cout<<dp[n][W]<<endl;
}
int main()
{
    while(cin>>n)
    {
        for(int i=0; i<n; i++)
            cin>>w[i]>>v[i];
        cin>>W;
        solve();
    }
    return 0;
}
/*
4
2 2
3 3
2 3
4 2
6
6

*/

记忆化搜索代码如下:

/*
01背包问题
根据书上所示的递归调用图可知,对于一个递归函数,
如果参数相同,那么返回的结果必然也应该是相同的,
于是第二次传入相同的参数结果是知道的,但是却还是进行计算浪费了时间
所以应该考虑把把第一次计算时的结果记录下来,以此节约时间。
*/
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=520;
int n,w[maxn],v[maxn],W,dp[maxn][20*maxn];
int fun(int pos,int sum)//pos是当前物品的位置,sun是当前容量。
{
    int ans=0;//最大价值。
    if(dp[pos][sum]>=0)//如果已经计算过,就直接使用之前的结果。
        return dp[pos][sum];
    if(pos==n)
        ans=0;
    else if(w[pos]>sum)//如果装不下该物品。
        return fun(pos+1,sum);
    else
        ans=max(fun(pos+1,sum),fun(pos+1,sum-w[pos])+v[pos]);
    dp[pos][sum]=ans;//将结果记录在数组中
}
void solve()
{
    memset(dp,-1,sizeof(dp));//初始化。
    cout<<fun(0,W)<<endl;
}
int main()
{
    while(cin>>n)
    {
        for(int i=0; i<n; i++)
            cin>>w[i]>>v[i];
        cin>>W;
        solve();
    }
    return 0;
}
/*
4
2 3
1 2
3 4
2 2
5
7(选择第0,1,3号物品)。
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值