第一层:1、输入 2、运算 3、输出
第二层:1、判断函数 2、输入数据 3、循环输出结果
第三层:计算
循环T组
每组判断
循环计算出多个可能和
每个可能和与k比较
相等
输出yes跳出循环
不相等
不跳出循环
比较完了,都不相等,输出no跳出循环
第四层:如何计算可能和 分组 一个相加,两个相加……以此类推
第五层:有n种药物,第一种吃了能转a[1]圈有t[1]片,第二种吃了能转a[2]圈有t[2]片,以此类推,第n种吃了能转a[n]圈有t[n]片,有人想通过吃药来转k圈(k是正整数),能否满足,能则输出yes,不能则输出no。
链接:https://www.nowcoder.com/questionTerminal/7f24eb7266ce4b0792ce8721d6259800
来源:牛客网
给定一个有n个正整数的数组A和一个整数sum,求选择数组A中部分数字和为sum的方案数。
当两种选取方案有一个数字的下标不一样,我们就认为是不同的组成方案。
输入描述:
输入为两行:
第一行为两个正整数n(1 ≤ n ≤ 1000),sum(1 ≤ sum ≤ 1000)
第二行为n个正整数Ai,以空格隔开。
输出描述:
输出所求的方案数
示例1
输入
5 15 5 5 10 2 3
输出
4
//递归会超时,只能过40%,用dp. dp[i][j]表示用前i个值组成和为j的方案个数(相比一维的,更容易理解一些)
#include <iostream>
#include <algorithm>
using namespace std;
//注意:最终结果int类型存不下,需要64位数据
//注意:dp不能放在main里,栈存不下。需要存在全局数据区
long long dp[1001][1001];
int main()
{
int n,sum;
cin>>n>>sum;
int p[1000];
for(int i = 1 ; i <= n ; i++)
cin>>p[i];
//初始化dp,用前i个组成和为0的方案,只有1种,就是什么都不取,和为0;
for (int i = 0 ; i < n ;i++)
{
dp[i][0] = 1;
}
//用0个元素不能组成1~sum
for (int j = 1 ; j < sum ;j++)
{
dp[0][j] = 0;
}
for (int i = 1 ; i <= n ;i++)
{
for (int j = 0 ; j<=sum ;j++)
{
if(p[i]<=j) dp[i][j] = dp[i-1][j]+dp[i-1][j-p[i]];
else dp[i][j] = dp[i-1][j];
}
}
cout<<dp[n][sum]<<endl;
return 0;
}
算法总结)寻找组合数,求出从整数1到n中和为m的所有组合
奋斗的小炎 2018-07-12 12:44:15 4591 收藏
分类专栏: 编程 算法与数据结构 python
版权
采用背包问题原理,仅考虑具有最大的数字n是否存在与结果集合中,考虑以下两种情形:
(1)n在集合中,剩下的n-1个数字需要组成一个和为n-m的组合;
(2)n不在集合中,剩下的n-1个数字仍需要组成和为m的组合;
由于需要给出所有的组合可能,因此是一个回溯的过程。
算法设计思路:
由于是个回溯递归的过程,因此需要首先给出递归终止条件:当需要求和的数字小于等于0或所有数字都用完了的时候,就是程序终止的时候。
用一个列表数组item存储当前的候选集合,result列表存放最终的满足条件的结果,当满足条件时,将item加入result中。
因此,回溯的代码如下:
def find_combine(item, n, m, result):
if n <= 0 or m <= 0:
return
if n == m:
result.append(item + [n])
item.append(n)
find_combine(item, n-1, m-n, result)
item.pop()
find_combine(item, n-1, m, result)
用一组数字,运行一下,这里假设n=9,m=10
if __name__ == '__main__':
item = []
result = []
find_combine(item, 9, 10, result)
for r in result:
print(r)
运行结果如下:
[9, 1]
[8, 2]
[7, 3]
[7, 2, 1]
[6, 4]
[6, 3, 1]
[5, 4, 1]
[5, 3, 2]
[4, 3, 2, 1]