CF189A Cut Ribbon(dp一维思想,完全背包最详细解析)

题目描述

Polycarpus has a ribbon, its length is nn . He wants to cut the ribbon in a way that fulfils the following two conditions:

  • After the cutting each ribbon piece should have length aa , bb or cc .
  • After the cutting the number of ribbon pieces should be maximum.

Help Polycarpus and find the number of ribbon pieces after the required cutting.

输入格式

The first line contains four space-separated integers nn , aa , bb and cc (1<=n,a,b,c<=4000)(1<=n,a,b,c<=4000) — the length of the original ribbon and the acceptable lengths of the ribbon pieces after the cutting, correspondingly. The numbers aa , bb and cc can coincide.

输出格式

Print a single number — the maximum possible number of ribbon pieces. It is guaranteed that at least one correct ribbon cutting exists.

题意翻译

给一长度为n的缎带,要求将其剪成若干长度为a,b,c的缎带,且缎带数量尽可能多。

输入格式: 输入仅一行,四个正整数n,a,b,c(n,a,b,c≤4000)。

输出格式: 输出仅一行,即缎带数量的最大值。

输入输出样例

输入 #1复制

5 5 3 2

输出 #1复制

2

输入 #2复制

7 5 5 2

输出 #2复制

2

dp解析,

#include<bits/stdc++.h>
using namespace std;
int n,a[12],f[120000];
int main() {
    cin>>n>>a[1]>>a[2]>>a[3];
    memset(f,-1,sizeof f);//为啥是-1,其他不行吗? 
    f[0]=0;//为啥一定要是f[0],我f[1]不行吗?
    for(int i=1;i<=3;i++)
        for(int j=a[i];j<=n;j++){
            if(f[j-a[i]]<0) continue;//当 j=a[i]为0我们就不用退出,或者踩到前面我们定义的f[j],我等下会解释为啥这样会可以统计出正确值。
            f[j]=max(f[j],f[j-a[i]]+1);//更新最大值,等下我也会解释,
        }
    cout<<f[n];//戚,为啥输出f[n],我输f[n-1]其他的不行吗?
    return 0;
}

1、首先我们考虑memset这个函数是初始0和-1;其他的必错;

 2,为啥我们f[0]=0;而不是f[1]=0;因为我们执行下面循环的判断,代表着我们刚刚开始循环的时候可以切下我们指定的彩带,也就是存下来。

 3.例如          如果是 5 5 3 2 

第一轮是a[1]=5 然后f[5]=1;
     第二轮的时候a[2]=3 会给f[3]赋值1;
             第三轮   a[3]=2 ,f[2]=1;这时候我们继续j++,发现循环到j=5,我们f[j-2]=f[3]=1;这个我们发现了  if(f[5-a[3]]<0) continue;不符合,所以我们可以执行下面的循环  f[j]=max(f[j],f[j-a[i]]+1);最后就是f[5]=2;为什么会这样呢,因为我们看成我们剪了一个长度为2的彩带,然后我们继续j++的时候发现当j=5,我们f【3】=1,可以继续执行循环相当于又可以剪一刀,这个时候我们由统计了一个f【5】的值,然后我们通过循环max取出最后的值f【n】就是我们要的答案。

 4.最后为啥是f[n],因为我们的背包是n,所以我们取f[n]。

最后,为什么这样减是最多的,因为我们用了 f[j]=max(f[j],f[j-a[i]]+1);//更新f[j]最大值,,这里我们最后输出的f【n】,代表背包体积是n;

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

算法编程张老师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值