如何找出数组中元素之和为特定数的最优组合
一 问题描述
给定一个含有n个元素的整形数组a,再给定一个和sum,求出数组中满足给定和的所有元素组合,
举个例子,设有数组a[5] = {1,2,3,4,5},sum = 7,则满足和为7的所有组合是
{5,2}
{4,3}
{4,2,1}
二 解法
把sum看成一个包裹的容量,数组的元素看成石头的重量,题目可以转化为求石头的组合,使
组合内的石头刚好放进包裹。
递归解法:包裹容量为sum,先把一块重量为 m 的石头放进去,剩下包裹容量为 (sum - m),
接下来递归地求在包裹容量为(sum - m)的前提下,有多少种石头的组合。
如下图所示,包容量为7,先把4放进去,剩余容量为3,容量为3的包裹,石头的组合有两种:
{2, 1}和{3}
算法:
1 先把石头的重量按照从小到大排序
2 用一个flag数组标记当前放入包裹的石头
3 优先选择重量大的石头放入包裹,可以减少递归的次数
三 代码实现
C++ 实现:
#include <stdio.h> #define N 5 int flag[N]; /* 从数组a[0]...a[t]找出和等于sum的组合 */ void how_many_sum(int *a, int sum, int t) { int i, success; if (sum == 0) { printf("找到一个组合\n"); for (i = 0; i < N; i++) { if (flag[i]) { printf("%d,", a[i]); } } printf("\n"); return; } success = 0; for (i = t; i >= 0; i--) { if (flag[i] == 0 && (sum - a[i]) >= 0) { flag[i] = 1; printf("把%d放入包裹,剩下容量为%d\n", a[i], sum-a[i]); how_many_sum(a, sum - a[i], i-1); printf("丢弃%d\n", a[i]); flag[i] = 0; success = 1; } } if (success == 0) { printf("无解\n"); } } int main() { int a[N] = {1,2,3,4,5}; int sum = 7; how_many_sum(a,sum,N-1); getchar(); return 0; }
以上转自:http://blog.csdn.net/kenby/article/details/6808663 下面是我自己用C#实现的代码
C#实现:
private static int N = 5; private int[] flag = new int[N]; [Test] public void CommonTest_01() { int[] a = {1,2,3,4,5}; int sum = 7; how_many_sum(a,sum,N-1); } void how_many_sum(int [] a,int sum,int t) { int i, success; if (sum == 0) { Debug.WriteLine("找到一个组合"); for (i = 0; i < N;i++) { if (flag[i] > 0) { Debug.Write(string.Format("{0},", a[i])); } } Debug.Write("=" + 7); Debug.WriteLine(""); return; } success = 0; for (i = t;i >=0;i--) { if (flag[i] == 0 && (sum - a[i]) >= 0) { flag[i] = 1; Debug.WriteLine(string.Format("把{0}放入包裹,剩下容量为{1}", a[i], sum - a[i])); how_many_sum(a, sum - a[i], i - 1); Debug.WriteLine(string.Format("丢弃{0}",a[i])); flag[i] = 0; success = 1; } } if (success == 0) { Debug.WriteLine("无解"); } }
作者:
吉桂昕
出处: http://www.cnblogs.com/jiguixin
我的新浪微博: http://weibo.com/jiguixin
本文版权归【吉桂昕】和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。如果觉得还有帮助的话,可以点一下右下角的【推荐】,希望能够持续的为大家带来好的技术文章!想跟我一起进步么?那就【关注】我吧。
出处: http://www.cnblogs.com/jiguixin
我的新浪微博: http://weibo.com/jiguixin
本文版权归【吉桂昕】和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。如果觉得还有帮助的话,可以点一下右下角的【推荐】,希望能够持续的为大家带来好的技术文章!想跟我一起进步么?那就【关注】我吧。