HDOJ(HDU).1258 Sum It Up (DFS)
HDOJ(HDU).1258 Sum It Up (DFS) [从零开始DFS(6)]
从零开始DFS
HDOJ.1342 Lotto [从零开始DFS(0)] — DFS思想与框架/双重DFS
HDOJ.1010 Tempter of the Bone [从零开始DFS(1)] —DFS四向搜索/奇偶剪枝
HDOJ(HDU).1015 Safecracker [从零开始DFS(2)] —DFS四向搜索变种
HDOJ(HDU).1016 Prime Ring Problem (DFS) [从零开始DFS(3)] —小结:做DFS题目的关注点
HDOJ(HDU).1035 Robot Motion [从零开始DFS(4)]—DFS题目练习
HDOJ(HDU).1241 Oil Deposits(DFS) [从零开始DFS(5)] —DFS八向搜索/双重for循环遍历
HDOJ(HDU).1258 Sum It Up (DFS) [从零开始DFS(6)] —DFS双重搜索/去重技巧
HDOJ(HDU).1045 Fire Net [从零开始DFS(7)]—DFS练习/check函数的思想
题意分析
每组数据给出要凑出的目标数字num和数字个数n,然后依次给出n个数字。要求从n个数字中选出若干个数字,是的数字之和为nun。重复的组合只输出一次。
和之前做过的选数字的题目类似,也可以采用DFS的思想来做。这道题与HDOJ.1342 Lotto [从零开始DFS(0)]及其的相似:每个数字有2种选择,选/不选,只要我选择的这些数字的和为num就行了。但是不难想到会有重复的组合出现,例如给出的样例3:
400 12 50 50 50 50 50 50 25 25 25 25 25 25
要求从12个数字中选择出若干数字使得总和为400,我们可以发现选择6个50和4个25即可。那么若按照HDOJ.1342的思想,选/不选,问题就会出现:要从6个25中选4个25,会有C(6,4)中情况,也就是说最后的结果会多出11组相同的解。这显然不符合题意。
问题的关键在于如何去重,最先想到也是最容易想到的就是把每组解保存下来,如果遇到重复的只输出一组即可。很明显这种方法实现起来耗费的工程量是巨大的,非常麻烦。回到DFS的核心:递归。我们对于递归做出一些约束,当满足一定条件时,下面搜索的解会造成重复,就终止递归。这样得到的解,均是非重复的。关键就是找到这样的条件,或者说为递归创造这样的条件。
上代码。
代码总览
/*
Title:HDOJ.1258
Author:pengwill
Date:2017-2-8
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int num,n,pos;
int a[15],b[15];
bool judge = false;
void output(int depth)
{
for(int i =0 ;i< depth; ++i)
if(!i) printf("%d",b[i]);
else printf("+%d",b[i]);
printf("\n");
}
void dfs(int depth,int sum,int pos)
{
if(sum == num) {judge = true;output(depth); return;}
if(sum>num) return;// 超出了 终止递归
if(pos>=n) return; //选择的数的位置超出数据范围
b[depth] = a[pos];
dfs(depth+1,sum+a[pos],pos+1);
while(pos+1<n&&a[pos] == a[pos+1]) pos++;//关键
dfs(depth,sum,pos+1);
}
int main()
{
//freopen("in.txt","r",stdin);
while(scanf("%d%d",&num,&n) && num){
printf("Sums of %d:\n",num);
for(int i = 0; i<n; ++i) scanf("%d",&a[i]);
judge = false;
dfs(0,0,0);
//output
if(judge == false) printf("NONE\n");
}
return 0;
}
还是按照HDOJ.1342 Lotto [从零开始DFS(0)]中写到的双重DFS的办法(即选/不选的思想),解决此题。
递归边界:当数字的和为num时,或者和超出了num,或者要选择的数字位置超出了n,终止搜索。
关键是下面这几句。
dfs(depth+1,sum+a[pos],pos+1);
while(pos+1<n&&a[pos] == a[pos+1]) pos++;//关键
dfs(depth,sum,pos+1);
首先是默认选择了pos这个位置的数字然后进行dfs。下面一个while循环表示如果下一个待选数字和本位置的待选数字一样的话,就跳过,一直跳到下一个待选数字不同的位置。如样例3:
400 12 50 50 50 50 50 50 25 25 25 25 25 25
就会从第一个50一直跳到最后一个50(下一个数字是25)。貌似看起来得不到正确结果,当然在第一层dfs不选择50的情况是没有正确解的。不放我们看一下下一层dfs,即选择了第一个50后的dfs。
进入第二层dfs依旧会有2种选择,要么选择第二个50,要么后续的50一个都不选。当然这时候一个50都不选的情况也是没有正确解的,继续看第三层。
进入第三层dfs还是会有2种选择,要么选择第三个50,要么后续的50一个都不选。但让后续50一个都不选的情况也没有正确解。
…………
依次类推,不难发现,这条while语句的作用就是:营造单一的选1个50,选2个50,选3个50这样的情况,从而避免了重复解的出现。
HDOJ(HDU).1258 Sum It Up (DFS)的更多相关文章
- (step4.3.4)hdu 1258(Sum It Up——DFS)
题目大意:输入t,n,接下来有n个数组成的一个序列.输出总和为t的子序列 解题思路:DFS 代码如下(有详细的注释): #include <iostream> #include <a ...
- HDU 1258 Sum It Up(DFS)
题目链接 Problem Description Given a specified total t and a list of n integers, find all distinct sums ...
- HDOJ(HDU).1016 Prime Ring Problem (DFS)
HDOJ(HDU).1016 Prime Ring Problem (DFS) [从零开始DFS(3)] 从零开始DFS HDOJ.1342 Lotto [从零开始DFS(0)] - DFS思想与框架 ...
- HDU 1258 Sum It Up(dfs 巧妙去重)
传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1258 Sum It Up Time Limit: 2000/1000 MS (Java/Others) ...
- hdu 1258 Sum It Up (dfs+路径记录)
pid=1258">Sum It Up Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (J ...
- hdu 1258 Sum It Up(dfs+去重)
题目大意: 给你一个总和(total)和一列(list)整数,共n个整数,要求用这些整数相加,使相加的结果等于total,找出所有不相同的拼凑方法. 例如,total = 4,n = 6,list = ...
- HDU 1258 Sum It Up (DFS)
Sum It Up Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total S ...
- HDU 1258 Sum It Up
Sum It Up Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total S ...
- 【HDOJ】1258 Sum It Up
典型的深搜,剪枝的时候需要跳过曾经搜索过的相同的数目,既满足nums[i]=nums[i-1]&&visit[i-1]==0,visit[i-1]==0可以说明该点已经测试过. #in ...
随机推荐
- linux基础——文件挂载,lamp安装
一. 文件挂载 lsblk -f 显示文件系统信息 mount -t vfat UUID="ffffffffff" /mnt 挂载到/mnt目录 Linux针对于各式U盘挂载方 ...
- 即刻开始使用Kotlin开发Android的12个原因(KAD 30)
作者:Antonio Leiva 时间:Jul, 11, 2017 原文链接:https://antonioleiva.com/reasons-kotlin-android/ 这组文章已到最后了,它们 ...
- 【isJson( jsonObj )】判断是否是JSON实例
判断是否是JSON实例: 原型:isJson( jsonObj ) 说明:判断对象是否是JSON实例 返回:[true | false] 示例: <% Set jsonObj1 = toJson ...
- Memcached命令-存储命令-查找命令-清理命令
Memcached set 存储命令 Memcached set 命令用于将 value(数据值) 存储在指定的 key(键) 中. 如果set的key已经存在,该命令可以更新该key所对应的原来的数 ...
- 一个简单的页面弹窗插件 jquery.pageMsgFrame.js
页面弹窗是网站中常用的交互效果,它可以强提示网站的某些信息给用户,或者作用于某些信息的修改等等功能. 这几天在做一个项目的时候,就顺捎把这个插件写一下,栽棵树,自己乘凉吧. 原创博文,转载请注明出处: ...
- 【Python 开发】第一篇:计算机基础
一.计算机基础 首先Python是一门编程语言 语言: 那什么是语言? 语言就是一种事物与另一种事物沟通的介质.所以说编程语言是程序员跟计算机沟通的介质. 什么是编程: 准确来说就是程序员用计算机所能 ...
- 主题模型 LDA 入门
主题模型 LDA 入门(附 Python 代码) 一.主题模型 在文本挖掘领域,大量的数据都是非结构化的,很难从信息中直接获取相关和期望的信息,一种文本挖掘的方法:主题模型(Topic Model ...
- 【算法分析】如何理解快慢指针?判断linked list中是否有环、找到环的起始节点位置。以Leetcode 141. Linked List Cycle, 142. Linked List Cycle II 为例Python实现
引入 快慢指针经常用于链表(linked list)中环(Cycle)相关的问题.LeetCode中对应题目分别是: 141. Linked List Cycle 判断linked list中是否有环 ...
- 一:HDFS 用户指导
1.hdfs的牛逼特性 Hadoop, including HDFS, is well suited for distributed storage and distributed processin ...
- Nodejs中关于模块的总结
关于Nodejs中的模块 概念 Nodejs在ECMAScript的基础上扩展并封装了许多高级特性,如文件访问.网络访问等,使得Nodejs成为一个很好的Web开发平台.基于Nodejs这个平台将We ...