杭州网站建设优化推广网络推广学校
杭州网站建设优化推广,网络推广学校,学新媒体运营要多少钱,酒店网站开发方案转载自#xff1a;http://blog.sina.com.cn/s/blog_7571423b01016707.html 编程求解#xff1a;输入两个整数 n 和 m #xff0c;从数列 1 #xff0c; 2 #xff0c; 3.......n 中随意取几个数 ,使其和等于 m , 要求将其中所有的可能组合列出来. 分析#xff1a; 主要思… 转载自http://blog.sina.com.cn/s/blog_7571423b01016707.html 编程求解输入两个整数 n 和 m 从数列 1 2 3.......n 中随意取几个数 ,使其和等于 m , 要求将其中所有的可能组合列出来. 分析 主要思想分治即midxm-idx 从最大数字n开始查找然后逐渐后退但每次查找只会在比当前数字大的方向进行组合尝试这样可以保证找到的组合不会重复。 参考代码 1: #include
2: #include
3: #includeSPAN styleCOLOR: #0000ffstring.h
4: void myDump(int aux[], int n)
5: {
6: for (int i0; i
7: if (aux[i]) // 0标示未选择该数字
8: printf(, i1);
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: // 递归结束条件dest0,说明找到一个组合dest0,说明该组合不满足和大于m)
18: // 如果idxn则说明已达到规定的最大数字范围为1-n)
19: if (dest 0 || idxn)
20: return;
21:
22: helper(dest, idx1, aux, n);
23: aux[idx] 1; // 标示选择了数字idx1
24:
25: //因为已经选择了idx即选择了数字idx1所以将m减去idx1
26: helper(dest-idx-1, idx1, aux, n);
27: aux[idx] 0; //无论结果是否满足都需要取消原来已选择的数字idx1然后尝试另一种组合
28: }
29:
30: void findCombination(int n, int m)
31: {
32: if(nm) //因为和为m所以大于m的数肯定不行
33: nm;
34:
35: int* auxnew 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: } ***************************************************************************** 解题思路: 显而易见, 当nm时, 肯定存在满足题目要求的子集. 由于数列1,2,...,n是正整数数列, 这使得所有的大于m的数加上数列最小元素1都会大于m, 所以当nm时我们只需要考虑子数列1,2,...,m即可. 当nm时,我们需要搜索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 itop; while( i-1 ) printf(%d\t, stack[i--] ); printf(\n); } int subsets( int n, int m ) { int i; int num0; int flag 1; if( n m ) n m; for( i n; flag i1; 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; }
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/89378.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!