附带条件的完全背包 - Cut Ribbon - CodeForces - 189A
Cut Ribbon
PROBLEMS
Polycarpus has a ribbon, its length is n. He wants to cut the ribbon in a way that fulfils the following two conditions:
After the cutting each ribbon piece should have length a, b or c.
After the cutting the number of ribbon pieces should be maximum.
Help Polycarpus and find the number of ribbon pieces after the required cutting.
Input
The first line contains four space-separated integers n, a, b and c (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 a, b and c can coincide.
Output
Print a single number — the maximum possible number of ribbon pieces. It is guaranteed that at least one correct ribbon cutting exists.
Examples
input
5 5 3 2
output
2
input
7 5 5 2
output
2
Note
In the first example Polycarpus can cut the ribbon in such way: the first piece has length 2, the second piece has length 3.
In the second example Polycarpus can cut the ribbon in such way: the first piece has length 5, the second piece has length 2.
分析
切割后每段长度为 a b c 可确定其为完全背包 则其状态转移方程为dp[j]=max(dp[j],dp[j-a]+1)
要想切割后段数最大并且长度为 a b c 就需要在添加限制条件 需要让每次状态转移中的dp[j-a]
成立 需要使其能够剪成 那限制条件就出来了 dp[j-a]
若j-a==0
同时也是成立
让 a b c 的长度将丝带分开 只需要将三个长度进行 dp 那最后的值必然为满足最大
代码
#include<stdio.h>
#include<algorithm>
using namespace std;
int j,n,a,b,c,dp[4010];
int main()
{
scanf("%d %d %d %d",&n,&a,&b,&c);
for(j=a; j<=n; j++)
if(dp[j-a]||j-a==0)
dp[j]=max(dp[j],dp[j-a]+1);
for(j=b; j<=n; j++)
if(dp[j-b]||j-b==0)
dp[j]=max(dp[j],dp[j-b]+1);
for(j=c; j<=n; j++)
if(dp[j-c]||j-c==0)
dp[j]=max(dp[j],dp[j-c]+1);
printf("%d",dp[n]);
}