转载自:http://blog.sina.com.cn/s/blog_7571423b01016707.html

编程求解:输入两个整数 n 和 m ,从数列 1 , 2 , 3.......n 中随意取几个数 ,使其和等于 m , 要求将其中所有的可能组合列出来.

分析:

主要思想:分治,即m=idx+m-idx
       从最大数字n开始查找,然后逐渐后退,但每次查找只会在比当前数字大的方向进行组合尝试,这样可以保证找到的组合不会重复。
参考代码

1: #include
2: #include
3: #include<<SPAN style="COLOR: #0000ff">string.h>
4: void myDump(int aux[], int n)
5: {
6: for (int i=0; i
7: if (aux[i]) // 0标示未选择该数字
8: printf("=", i+1);
9: printf("\n");
10: }
11:
12: void helper(int dest, int idx, int aux[], int n)
13: {
14: if (dest == 0) // m减为0时,找到一个组合,输出
15: myDump(aux, n);
16:
17: // 递归结束条件:dest=0,说明找到一个组合;dest<0,说明该组合不满足(和大于m);
18: // 如果idx=n,则说明已达到规定的最大数字(范围为1-n)
19: if (dest <= 0 || idx==n)
20: return;
21:
22: helper(dest, idx+1, aux, n);
23: aux[idx] = 1; // 标示选择了数字idx+1
24:
25: //因为已经选择了idx,即选择了数字idx+1,所以将m减去idx+1
26: helper(dest-idx-1, idx+1, aux, n);
27: aux[idx] = 0; //无论结果是否满足,都需要取消原来已选择的数字idx+1,然后尝试另一种组合
28: }
29:
30: void findCombination(int n, int m)
31: {
32: if(n>m) //因为和为m,所以大于m的数肯定不行
33: n=m;
34:
35: int* aux=new int[n];
36: memset(aux, 0, n*sizeof(int));
37:
38: helper(m, 0, aux,n);
39:
40: delete[] aux;
41: }
42:
43: int main()
44: {
45: int n,m;
46: scanf("%d,%d",&m,&n);
47:
48: findCombination(n,m);
49:
50: getchar();
51: return 0;
52: }

*****************************************************************************

解题思路:
    显而易见, 当n>m时, 肯定存在满足题目要求的子集. 由于数列1,2,...,n是正整数数列, 这使得所有的大于m的数加上数列最小元素1都会大于m, 所以当n>m时我们只需要考虑子数列1,2,...,m即可.
     当n<=m时,我们需要搜索1,2,...,n中符合条件的子集. 实际上, 我们可以将原问题分解成两个子问题:
子问题一: 在n个数的数列,我们取n, 然后原问题就变为找出1,2,...,n-1中和为m-n的所有子集,然后将所有的子集都加上元素n就得到了原问题的部分解集;
子问题二: 我们不取n, 原问题就变为找出1,2,...,n-1中和为m的所有子集.
联合两个子问题的解, 便得到了原问题的解集.

我们用subsets( n, m) 表示原问题, 那么原问题可表示为子问题 subsets(n-1, m) 和subsets( n-1, m-n)的解集的并集.
    即:   subsets( n, m)  = subsets(n-1, m) U subsets( n-1, m-n)
    实际中,可采用回溯的方法进行求解. 后面附有完整的代码.

实际的搜索方法类似于二叉树的方法, 去除不符合条件的解. 例如下面的二叉树就表示了1,2,...,n的全组合的求解过程. 左边分支表示取,右边的分支表示舍. 针对于0-1背包问题, 八皇后问题, 射击十次命中九十环的打法问题等等, 则需要剪除掉一些不符合条件的子树.

#include <stdio.h>
#include <assert.h>
#include <time.h>

#define MAXN 1000

int stack[MAXN];
int top = -1;
void push( int e )
{
 assert( top < MAXN );
 stack[++top] = e;
}

void pop( )
{
 assert( top > -1 );
 top--;
}

void clear()
{
 top = -1;
}

void printStack( )
{
 int i=top;
 while( i>-1 )
  printf("%d\t", stack[i--] );
 printf("\n");
}

int subsets( int n, int m )
{
 int i;
 int num=0;
 int flag = 1;

if( n > m )
  n = m;

for( i = n; flag && i>=1; i-- )
 {
  
  push( i );
  
  
  if( m-i == 0 )
  {
   num++;
   printStack();
  }
  else
  {
   
   
   if( (i-1)*i/2 < (m-i) )
   {
    pop();
    flag = 0;
    continue;
   }

num += subsets( i-1, m-i );
  }
  
  
  pop();
 }

return num;
}

void testSubsets()
{
 assert( 1 == subsets( 1, 1 ) );
 printf( "\n\n" );
 assert( 0 == subsets( 1, 2 ) );
 printf( "\n\n" );
 assert( 3 == subsets( 5, 6 ) );
 printf( "\n\n" );
 assert( 5 == subsets( 7, 7 ) );
}

int main()
{
 testSubsets( );

clock_t start = clock();
 subsets( 50, 50 );
 clock_t duration = clock() - start;
 printf("it takes %d seconds\n", duration/CLOCKS_PER_SEC );
 return 0;
}

输入两个整数 n 和 m ,从数列 1 , 2 , 3.......n 中随意取几个数 ,使其和等于 m相关推荐

  1. 算法--中兴面试:输入两个整数 n 和 m,从数列1,2,3.......n 中随意取几个数, 使其和等于 m

    转载请注明原文出处:http://blog.csdn.net/baidu_37107022/article/details/75125846 Q题目 编程求解 输入两个整数 n 和 m,从数列1,2, ...

  2. C++实现输入两个整数n和m,从数列1,2,3...n中随意取几个数,使其和等于m,要求列出所有的组合

    题目:C++实现输入两个整数n和m,从数列1,2,3...n中随意取几个数,使其和等于m,要求列出所有的组合 用到了组合的思想 #include<iostream> #include< ...

  3. 输入两个整数n和m,从数列1,2,3,……n中随意取几个数,使其和等于m 转载

    题目:编程求解,输入两个整数n和m,从数列1,2,3,--n中随意取几个数,使其和等于m.要求将所有的可能组合列出来. 分析:分治的思想.可以把问题(m,n)拆分(m - n, n -1)和(m, n ...

  4. 输入两个整数n和m,从1-n中随意取几个数,使其和等于m

    编程求解,输入两个整数n和m,从数列1,2,3,--n中随意取几个数,使其和等于m.要求将所有的可能组合列出来. 求解思路: 1.首先判断,如果n>m,则n中大于m的数不可能参与组合,此时置n ...

  5. ACMNO.31 C语言-宏求余 输入两个整数,求他们相除的余数。用带参的宏来实现,编程序。

    题目描述 输入两个整数,求他们相除的余数.用带参的宏来实现,编程序. 输入 a b两个数 输出 a/b的余数 样例输入 3 2 样例输出 1 来源/分类 C语言 题目截图: 思路: 这个是求余数,应该 ...

  6. ACMNO.7 输入两个正整数m和n,求其最大公约数和最小公倍数。 输入 两个整数 输出 最大公约数,最小公倍数 样例输入 5 7 样例输出 1 35

    题目描述 输入两个正整数m和n,求其最大公约数和最小公倍数. 输入 两个整数 输出 最大公约数,最小公倍数 样例输入 5 7 样例输出 1 35 来源/分类 C语言 示例照片: 设计思路: 本题最难的 ...

  7. python输入两个整数按先大后小的顺序输出_指针变量:输入a和b两个整数,按先大后小的顺序输出a和b。...

    #include int main() { int *p1,*p2,*p,a,b; printf("please enter two integer numbers:"); sca ...

  8. ytu 1057: 输入两个整数,求他们相除的余数(带参的宏 + 模板函数 练习)

    1057: 输入两个整数,求他们相除的余数 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 177  Solved: 136 [Submit][Stat ...

  9. 输入两个整数序列。其中一个序列表示栈的push顺序, 判断另一个序列有没有可能是对应的pop顺序。

    题目:输入两个整数序列.其中一个序列表示栈的push顺序,判断另一个序列有没有可能是对应的pop顺序.为了简单起见,我们假设push序列的任意两个整数都是不相等的. 比如输入的push序列是1.2.3 ...

最新文章

  1. SQLServer Date
  2. WinAPI: midiOutGetNumDevs - 获取 MIDI 输出设备的数目
  3. 华为鸿蒙系统技术细节盘点
  4. WCF rest 的帮助页面和缓存机制
  5. linux 下环境变量设置
  6. 前端vue显示柱状图_Vue—Echarts 柱状图
  7. 数据仓库之电商数仓-- 2、业务数据采集平台
  8. “SqlNullValueException: Data is Null. This method or property cannot be called on Null values.”的解决方案
  9. 44. Element insertBefore() 方法
  10. 【语音识别】基于DTW算法实现0~9数字含Matlab源码
  11. fseek函数c语言_使用示例的C语言中的fseek()函数
  12. iPhone 快捷指令 文本朗读
  13. python 读写pcd
  14. Tegra TX1 build tensorflow r1.1
  15. 网络编程 3 tcp通信
  16. NLP训练营学习记录(一)
  17. Terraform的安装
  18. 声纹识别--基础学习笔记
  19. 使用码云和博客园学习简易教程
  20. note9电量android系统应用,小米-Note-标准版-crDroid-V5.3-安卓9.0.0-来去电归属T9-农历等-多功能本地化增强适配...

热门文章

  1. python3文件的编码类型是什么_Python3编码类型有哪些?怎么转换?
  2. python mssql github_GitHub上最热门的开源项目都在这里了
  3. 颜宁问4对科研夫妻:男科学家怎样平衡事业家庭?
  4. 机械史上最复杂的巅峰之作,这才是最强大脑!
  5. 学霸真的比学渣更讨女孩子欢心吗?
  6. 你吃的瓜子仁,真是老奶奶磕出来的?!
  7. 每日一笑 | 终于知道为什么胖了之后气质会垮了
  8. 新一代来袭︱不只是舒适,简直是享受,Google公司用的腰靠,到底有什么秘密?...
  9. 人工智能路上,怎么能少了它!
  10. 据说这篇总结覆盖了一般Python开发面试中可能会问到的大部分问题