很久之前看过这个题目,但是没有仔细整理,直到现在看基础才想到这两个题。这两个题非常经典也非常类似。接下来分别介绍。

部分和问题

题目描述

给定整数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的方法数的更多相关文章

  1. 数字和为sum的方法数

    [编程题] 数字和为sum的方法数 给定一个有n个正整数的数组A和一个整数sum,求选择数组A中部分数字和为sum的方案数. 当两种选取方案有一个数字的下标不一样,我们就认为是不同的组成方案. 输入描 ...

  2. 数字和为sum的方法数(动态规划)

    题目描述 给定一个有n个正整数的数组A和一个整数sum,求选择数组A中部分数字和为sum的方案数.当两种选取方案有一个数字的下标不一样,我们就认为是不同的组成方案. 输入描述: 输入为两行: 第一行为 ...

  3. 动态规划:数字和为sum的方法数

    题目描述 给定一个有n个正整数的数组A和一个整数sum,求选择数组A中部分数字和为sum的方案数.当两种选取方案有一个数字的下标不一样,我们就认为是不同的组成方案. 输入描述: 输入为两行: 第一行为 ...

  4. Problem C: 动态规划基础题目之数字三角形

    Problem C: 动态规划基础题目之数字三角形 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 208  Solved: 139[Submit][Sta ...

  5. Leetcode之深度优先搜索(DFS)专题-129. 求根到叶子节点数字之和(Sum Root to Leaf Numbers)

    Leetcode之深度优先搜索(DFS)专题-129. 求根到叶子节点数字之和(Sum Root to Leaf Numbers) 深度优先搜索的解题详细介绍,点击 给定一个二叉树,它的每个结点都存放 ...

  6. 【动态规划】Vijos P1218 数字游戏(NOIP2003普及组)

    题目链接: https://vijos.org/p/1218 题目大意: 一个N个数的环,分成M块,块内的数求和%10,最后每块地值累乘,求最大和最小. n(1≤n≤50)和m(1≤m≤9)太小了可以 ...

  7. 数字组合 · Combination Sum

    不能重复: [抄题]: 给出一个候选数字的set(C)和目标数字(T),找到C中所有的组合,使找出的数字和为T.C中的数字可以无限制重复被选取. 例如,给出候选数组[2,3,6,7]和目标数字7,所求 ...

  8. LeetCode 129. 求根到叶子节点数字之和(Sum Root to Leaf Numbers)

    题目描述 给定一个二叉树,它的每个结点都存放一个 0-9 的数字,每条从根到叶子节点的路径都代表一个数字. 例如,从根到叶子节点路径 1->2->3 代表数字 123. 计算从根到叶子节点 ...

  9. sqlserver可将字符转成数字再进行sum,如果varchar类型中存放的都是数字

    sqlserver语法: select sum(cast(score as int)) as score from 表名; 注意:int是整型,在实际操作中根据自己需要的类型转换.

随机推荐

  1. Hibernate总结之Hello,World

    1. 引入相关maven依赖: <dependency> <groupId>org.hibernate</groupId> <artifactId>hi ...

  2. 蓝色的cms企业记账管理后台模板源码——后台

    链接:http://pan.baidu.com/s/1bpxKGBP 密码:suda

  3. MGR Switch single-Primary to Muti_primary

    MGR single_primary 切换 Muti-Primary 模式 root@localhost [(none)]>select * from performance_schema.re ...

  4. ansible 下lineinfile详细使用 【转】

    转自 ansible 下lineinfile详细使用 - 散人 - 51CTO技术博客http://zouqingyun.blog.51cto.com/782246/1882367 一.简述 这几天在 ...

  5. MySQL启动很慢的原因

    我们在启动MySQL的时候,常常会遇到的是, 当执行启动命令后,它会"Start MySQL ....." 一直不停的执行,也不中断,也不成功 这里会出现此现象的原因有以下三条: ...

  6. java基础6 面向对象的详解

    本文知识点(目录): 1.1.万物皆对象    1.2.面向对象的概述    1.3.面向对象(java语言)与面向过程(C语言)对比    1.4.面向过程    1.5.对象    1.6.面向对 ...

  7. PHP解决并发问题的几种实现

    对于商品抢购等并发场景下,可能会出现超卖的现象,这时就需要解决并发所带来的这些问题了 在PHP语言中并没有原生的提供并发的解决方案,因此就需要借助其他方式来实现并发控制. 方案一:使用文件锁排它锁 f ...

  8. HDU 1285 确定比赛名次(拓扑排序模板)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1285 题目大意:有N个比赛队(1<=N<=500),编号依次为1,2,3,....,N进行 ...

  9. python爬取漫画

    抓取漫画的网址是:sf互动传媒 抓取漫画的由来也是看了知乎上有人说用爬取漫画,然后自己也玩玩 首页中每个漫画的url是类似这样存储的: <tr> <td height="3 ...

  10. 亲手安装RabbitMq 3.7.2 并安装Trace插件

    ===============================================================================================1.安装E ...