[动态规划]经典之01背包

传送门

思路

很显然这就是一个01背包经典题目,对于每一个“物品”都可以选择采或者不采。
采的话那就获得了本物品的价值并且花费了采药的时间。
不采的话那就既不获得本物品的价值也不花费时间。

状态转移方程为

F [ i ] [ j ] = m a x { F [ i − 1 ] [ j − w [ i ] ] + v [ i ] , f [ i − 1 ] [ j ] } F[i][j] = max\{F[i-1][j-w[i]]+v[i],f[i-1][j]\} F[i][j]=max{F[i1][jw[i]]+v[i],f[i1][j]}

F(i,j)表示当拥有j个时间时选取前i件物品的最优解

#include <cstdio>
int w[102],v[102];
int f[120][1200];
int n,C;
int max(int x,int y){return x>y?x:y;}
int main()
{
    register int i,j;
   // freopen("1.in","r",stdin);
    scanf("%d%d",&C,&n);
    for(i=1;i<=n;i++)scanf("%d%d",&w[i],&v[i]);
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=C;j++)
        {
            if(j < w[i])f[i][j] =f[i-1][j];//时间不够肯定采不了
            else
            {
                f[i][j] = max(f[i-1][j],f[i-1][j-w[i]]+v[i]);
            }
            
        }
    }
    printf("%d\n",f[n][C]);

    return 0;
}

优化

仔细想想,你所申请的数组其实有很大的浪费,其实用一个一维数组也可以ac这一题

F [ j ] = m a x { F [ j − w [ i ] ] + v [ i ] , f [ j ] } F[j] = max\{F[j-w[i]]+v[i],f[j]\} F[j]=max{F[jw[i]]+v[i],f[j]}

没错只是少了个i,也就是空间由f[m][n]压缩成了f[n],节省了不少空间,但是这样的话就意味着第二重循环不能从0到n,这是为什么呢?
因为如果从小到大循环由于前面的数字被更新过,你后面更新出来的数字是个什么玩意?
#include <cstdio>

int n,m;
int f[1050];
int w[100];
int v[100];
int max(int x,int y){return x>y?x:y;}
int main()
{
    register int i,j;
    freopen("in","r",stdin);
    scanf("%d",&n);
    scanf("%d",&m);
    for(i=1;i<=m;i++)
    {
        scanf("%d%d",w+i,v+i);//嫖来的更方便的方法,仔细想想有点道理
    }
    for(i=1;i<=m;i++)
    {
        for(j=n;j>=0;j--)
        {
            if(j >= w[i])
            	f[j] = max(f[j-w[i]] + v[i],f[j]);
        }
    }
    printf("%d\n",f[n]);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值