动态规划:部分和问题和数字和为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是整型,在实际操作中根据自己需要的类型转换.
随机推荐
- net 加密-解密
#region DES加密 解密 //key:32位 public string DESEncrypt(string strSource, byte[] key) { System.Security. ...
- wepy 使用组件时一个注意事项。。。
组件传值prop 必须使用指定引用地址的数据 如果像下面这样 取为空shop 中的phone ,后续获取数据或就算 shop中有phone元素 子组件也无法获取到修改后的值 <template& ...
- java正则: 忽略大小写匹配
import java.util.regex.Matcher; import java.util.regex.Pattern; import com.sun.org.apache.xerces.int ...
- 使用navicat for sqlserver 把excel中的数据导入到sqlserver数据库
以前记得使用excel向mysql中导入过数据,今天使用excel向sqlserver2005导入了数据,在此把做法记录一下 第一步:准备excel数据,在这个excel中有3个sheet,每个she ...
- caffe Python API 之Solver定义
from caffe.proto import caffe_pb2 s = caffe_pb2.SolverParameter() path='/home/xxx/data/' solver_file ...
- linux系统cpu使用100%的命令
for i in `seq 1 $(cat /proc/cpuinfo |grep "physical id" |wc -l)`; do dd if=/dev/zero of=/d ...
- angular项目中使用jquery的问题
1.使用npm命令往项目中添加jQuery. npm install jquery --save 2.在你想要用jQuery的组件中添加. import * as $ from "jquer ...
- maven实战系列
Maven实战(一)安装和配置 Maven实战(二)构建简单Maven项目 Maven实战(三)Eclipse构建Maven项目 Maven实战(四)生命周期 Maven实战(五)坐标详解 Maven ...
- window下线程同步之(Event Objects(事件))
Event 方式是最具弹性的同步机制,因为他的状态完全由你去决定,不会像 Mutex 和 Semaphores 的状态会由类似:WaitForSingleObject 一类的函数的调用而改变,所以你可 ...
- AC日记——825G - Tree Queries
825G - Tree Queries 思路: 神题,路径拆成半链: 代码: #include <cstdio> #include <cstring> #include < ...