题目描述
到中午了,机器猫要吃猫粮了。
机器猫掏出 n 份食物,第 i 份食物含有的能量为 w[i]。机器猫可以吃掉其中一些食物,获得这些食物的能量之和。
机器猫又不想变得太胖又不想变得太瘦,所以指定了一个目标区间 [l,r]。显然,可能有很多种选择食物的方式可以达成这个目标,因此机器猫想知道方案总数。
输入格式
第一行,三个正整数 n,l,r。
第二行,n 个正整数,表示每一份食物含有的能量 w[i]。
输出格式
仅一行,一个整数,表示方案数。
输入输出样例
输入 #1复制
4 70 85 10 10 20 50
输出 #1复制
4
说明/提示
样例解释
所有方案如下:
选择食物 1, 2, 4,能量 10+10+50 = 70
选择食物 1, 3, 4,能量 10+20+50 = 80
选择食物 2, 3, 4,能量 10+20+50 = 80
选择食物 3, 4,能量 50+20 = 70
共 4 种方案。
数据规模与约定
对于 50%50% 的数据,满足 n≤20。
对于 100%100% 的数据,满足 n≤40,20≤w[i]≤100,l≤r≤300。
提示:w[i] 在范围内均匀随机生成。
较为简单的方法是深度优先搜索DFS
但是效率比较高的方法还是动态规划
1.定义状态:
由于有食物种类,能量大小以及方案数量三个变量
所以我们采用二维数组表示状态
f[i][j]表示选择前i种食物可以得到不同能量和为j的总数
2.写出状态转移方程:
第i种食物都有两种选择:要么选,要么不选
不选:f[i][j]=f[i-1][j];
选:f[i][j]+=f[i-1[j-w[i]];
3.根据状态转移方程找出递推顺序:
f[i][j]需要前面的数值往后进行动态规划
所以我们选择顺推顺序
4.处理递推的边界:
当能量为0的时候,只有一种情况:所有的食物都不挑选
for (int i = 1; i <= n; i++)cin >> a[i], f[i][0] = 1;
f[0][0] = 1;
5.找出结果:
我们要求的状态其实也就是在这n种食物当中选择符合能量需求的状态方案总数:
for (int j = l; j <= r; j++) {
ans += f[n][j];
}
接下来直接上代码:
#include <iostream>
using namespace std;
int ans, n, l, r, a[50], f[50][500];
int main() {
cin >> n >> l >> r;
for (int i = 1; i <= n; i++)cin >> a[i], f[i][0] = 1;
f[0][0] = 1;
for (int i = 1; i <= n; i++)
for (int j = 0; j <= r; j++) {
f[i][j] = f[i - 1][j];
if (j - a[i] >= 0)f[i][j] += f[i - 1][j - a[i]];
}
for (int j = l; j <= r; j++) {
ans += f[n][j];
}
cout << ans;
}
希望大佬指点!