动态规划:部分和问题和数字和为sum的方法数
很久之前看过这个题目,但是没有仔细整理,直到现在看基础才想到这两个题。这两个题非常经典也非常类似。接下来分别介绍。
部分和问题
题目描述
给定整数a1、a2、.......an,判断是否可以从中选出若干数,使它们的和恰好为K。
输入
首先,n和k,n表示数的个数,k表示数的和。
接着一行n个数。
(1<=n<=20,保证不超int范围)
输出
如果和恰好可以为k,输出“YES”,并按输入顺序依次输出是由哪几个数的和组成,否则“NO”
样例输入
4 13
1 2 4 7
样例输出
YES
2 4 7
思路:
很明显,这是一道简单的dfs搜索,直接理由dfs的定义解决,不过最难点是如何实现剪枝,减少不必要的时间浪费,这道题需要减掉的是
1.从当前状态如何转移都不会存在解
2.当sum超过k时,也没必要继续搜索
代码:
//没有剪枝的代码
#include<cstdio>
#include<iostream>
using namespace std;
int n,k,a[],b[];
bool dfs(int x,int sum) //从左到右遍历一遍可得解
{
if(sum>k)
return false;
if(x==n)
return sum==k; //如果前n项计算过了,返回sum=k是否相等
if(dfs(x+,sum))
{
b[x]=; //如果不加上a[x]的情况,标记为0;
return true;
}
if(dfs(x+,sum+a[x]))
{
b[x]=; //如果加上a[x]的情况,标记为1;
return true;
}
return false;
}
int main()
{
while(scanf("%d%d",&n,&k)!=EOF)
{
for(int i = ; i<n; i++)
scanf("%d",&a[i]);
if(dfs(,))
{
printf("YES\n");
for(int i=; i<n; i++)
if(b[i])
printf("%d ",a[i]);
printf("\n");
}
else
printf("NO\n");
}
return ;
}
和为sum的方法数
题目描述:
给定一个有n个正整数的数组A和一个整数sum,求选择数组A中部分数字和为sum的方案数。
当两种选取方案有一个数字的下标不一样,我们就认为是不同的组成方案。
输入:
输入为两行:
第一行为两个正整数n(1 ≤ n ≤ 1000),sum(1 ≤ sum ≤ 1000)
第二行为n个正整数A[i](32位整数),以空格隔开。
输出:
输出所求的方案数
样例输入
5 15
5 5 10 2 3
样例输出
4
思路一:
用递归加回溯的方法,找出数组的所有子集。
若子集和等于整数sum,则数组A中部分数字和为sum的方案数加一。
可优化的地方在子集当前和大于sum,则跳出该分支,因为数组A为正整数,之后的子集和只会越来越大。
这种方法缺点在于:时间复杂度大,为 O(2 ^ n) ,递归调用次数过多,容易爆栈。
#include<iostream>
#include<vector>
using namespace std;
int n, sum, count = ; void help(vector<int>& a, int pos, int part) { if (part == sum)
count++; if (part > sum)
return; for(int i=pos; i<n; i++) {
part += a[i];
help(a, i+, part);
part -= a[i];
}
} int main(){
cin>>n>>sum; vector<int> a(n);
for(int i=; i<n; i++)
cin>>a[i]; help(a, , ); cout<<count<<endl; return ; }
思路二:
用动态规划,类似01背包问题,f(i , j )表示前i 个数中和为 j 的方案数, 则 若 j >= a[i], f ( i ,j) = f(i -1, j)+ f (i - 1,j - a[i] );
否则, f ( i ,j) = f(i -1, j)。
可优化地方:由于二维数组中,第i行 只与第 i - 1 行有关,所有我们若从 最后一列 开始更新数组,则可用一维数组来保存先前状态。
时间复杂度为:O( n * sum ) 。
#include<iostream>
#include<vector>
using namespace std; int main() {
int n, sum;
cin>>n>>sum; vector<long long> a(sum+);
vector<int> b(n); for(int i=; i<n; i++)
cin>>b[i]; a[] = ; for (int i=; i<n; i++)
for (int j=sum; j>=b[i]; j--)
a[j] += a[j-b[i]]; cout<<a[sum]<<endl; return ; }
动态规划:部分和问题和数字和为sum的方法数的更多相关文章
- 数字和为sum的方法数
[编程题] 数字和为sum的方法数 给定一个有n个正整数的数组A和一个整数sum,求选择数组A中部分数字和为sum的方案数. 当两种选取方案有一个数字的下标不一样,我们就认为是不同的组成方案. 输入描 ...
- 数字和为sum的方法数(动态规划)
题目描述 给定一个有n个正整数的数组A和一个整数sum,求选择数组A中部分数字和为sum的方案数.当两种选取方案有一个数字的下标不一样,我们就认为是不同的组成方案. 输入描述: 输入为两行: 第一行为 ...
- 动态规划:数字和为sum的方法数
题目描述 给定一个有n个正整数的数组A和一个整数sum,求选择数组A中部分数字和为sum的方案数.当两种选取方案有一个数字的下标不一样,我们就认为是不同的组成方案. 输入描述: 输入为两行: 第一行为 ...
- Problem C: 动态规划基础题目之数字三角形
Problem C: 动态规划基础题目之数字三角形 Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 208 Solved: 139[Submit][Sta ...
- Leetcode之深度优先搜索(DFS)专题-129. 求根到叶子节点数字之和(Sum Root to Leaf Numbers)
Leetcode之深度优先搜索(DFS)专题-129. 求根到叶子节点数字之和(Sum Root to Leaf Numbers) 深度优先搜索的解题详细介绍,点击 给定一个二叉树,它的每个结点都存放 ...
- 【动态规划】Vijos P1218 数字游戏(NOIP2003普及组)
题目链接: https://vijos.org/p/1218 题目大意: 一个N个数的环,分成M块,块内的数求和%10,最后每块地值累乘,求最大和最小. n(1≤n≤50)和m(1≤m≤9)太小了可以 ...
- 数字组合 · Combination Sum
不能重复: [抄题]: 给出一个候选数字的set(C)和目标数字(T),找到C中所有的组合,使找出的数字和为T.C中的数字可以无限制重复被选取. 例如,给出候选数组[2,3,6,7]和目标数字7,所求 ...
- LeetCode 129. 求根到叶子节点数字之和(Sum Root to Leaf Numbers)
题目描述 给定一个二叉树,它的每个结点都存放一个 0-9 的数字,每条从根到叶子节点的路径都代表一个数字. 例如,从根到叶子节点路径 1->2->3 代表数字 123. 计算从根到叶子节点 ...
- sqlserver可将字符转成数字再进行sum,如果varchar类型中存放的都是数字
sqlserver语法: select sum(cast(score as int)) as score from 表名; 注意:int是整型,在实际操作中根据自己需要的类型转换.
随机推荐
- 【代码优化】调用optional delegates的最佳方法
[转载请注明出处]http://www.cnblogs.com/lexingyu/p/3932475.html 本文是以下两篇blog的综合脱水,感谢两位作者为解放码农生产力所做的深入思考=.= Sm ...
- HDU 2516 取石子游戏 (找规律)
题目链接 Problem Description 1堆石子有n个,两人轮流取.先取者第1次可以取任意多个,但不能全部取完.以后每次取的石子数不能超过上次取子数的2倍.取完者胜.先取者负输出" ...
- sublime 直接运行php代码
只需要简单的配置就可以进行 操作. 首先配置php环境变量 配置完成后打开sublime 点击新编译系统 { "cmd": ["php", "$fil ...
- xshell5破解版下载
http://www.pc6.com/softview/SoftView_507840.html
- VueJS $refs 在 ElementUI 中遇到的问题
表单验证的时候 $refs 拿不到 暂且是用 $nextTick 解决,具体原因有待研究 假入在 created 中注册时间来验证 validate,那就放在mounted中 或者...注册了 ev ...
- fileIO和OS操作文件和目录
1.FileIO操作文件 # 文件IO,读取文件和创建文件 # 1.读取键盘输入 x=input("please input number") print("您输入的是& ...
- http 之cookie和session
cookie和session 关于http: 1.http是:无状态.短连接 2.http的请求生命周期:给服务端发送一个请起头,通过域名提取url,通过路由关系匹配,再通过函数+html进行模板加 ...
- IT人员必备linux安全运维之Ssh用途、安全性、身份认证以及配置……【转】
SSH一般用途 提供shell,解决telnet不安全的传输 1.修改默认ssh默认端口 vi /etc/ssh/sshd_config 修改之后重启 >systemctl restart ss ...
- 多个id或class属性相同的元素绑定事件
<td class="tools"><a href="javascript:void(0);" status="0" na ...
- python redis-string、list、set操作
string操作 redis中的string在内存中都是按照一个key对应一个value来存储的 方法: set() 方法 : 写入一条数据 mset() 方法: 写入多条数据 , 可是Key-Val ...