动态规划的背包问题《数字组合》
Posted JunMain
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态规划的背包问题《数字组合》相关的知识,希望对你有一定的参考价值。
数字组合
题目描述
给定 N个正整数 A_1, A_2,…,A_N,从中选出若干个数,使它们的和为 M,求有多少种选择方案。
输入格式
第一行包含两个整数 N 和 M。
第二行包含 N 个整数,表示 A_1,A_2,…,AN。
输出格式
给定 N 个正整数 A1,A2,…,AN,从中选出若干个数,使它们的和为 M,求有多少种选择方案。
输入格式
第一行包含两个整数 N 和 M。
第二行包含 N 个整数,表示 A1,A2,…,AN。
输出格式
包含一个整数,表示可选方案数。
数据范围
1≤N≤100,
1≤M≤10000,
1≤Ai≤1000,
答案保证在 int 范围内。
输入样例:
4 4
1 1 2 2
输出样例:
3
这边看出来一个集合只有两种状态划分====> 01背包
有限制的选择问题========>背包
- 集合f[i][j] 的含义:从前i个数选择,和为j 的选法集合, 属性是:count
- 集合划分:第i个数字选或者不选
- 选:f[i-1][j-w[i]] 从前i-1个数中选,和为j-w[i]集合的个数 (限制条件 j-w[i] >= 0)
- 不选 f[i-1][j] 从前i-1个数选,和为j集合的个数
- 初始化边界:(实在推不出来就根据样例手推)
- f[i][0] = 1 前i个数 和为0选法集合的个数是1 都不选
- f[0][i] = 0
注意我们我们的转移方程一定是根据我们的定义推到的, 不同的定义推到的方程不一样
#include <bits/stdc++.h>
using namespace std;
int f[110][100010], w[100010];
int main()
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i ++ ) scanf("%d", &w[i]);
for (int i = 0; i <= n; i ++ ) f[i][0] = 1;
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= m; j ++)
{
f[i][j] = f[i-1][j];
if (j - w[i] >= 0) f[i][j] += f[i-1][j-w[i]];
}
cout << f[n][m];
return 0;
}
以上是关于动态规划的背包问题《数字组合》的主要内容,如果未能解决你的问题,请参考以下文章