zoukankan      html  css  js  c++  java
  • 如何找出数组中元素之和为特定数的最优组合

    一 问题描述

    给定一个含有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}

    image

     

    算法:

    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("无解");
                }
            }  
  • 相关阅读:
    Java以指定格式输入数字
    毕向东JAVA视频讲解(第六课)
    毕向东JAVA视频讲解(四五课)
    毕向东JAVA视频讲解笔记(前三课)
    C++ Primer笔记整理
    map的详细用法
    opencv中的矩阵操作
    Matlab程序 转C++/Opencv基于Mat 不可不知的17个函数
    目标检测的图像特征提取之(三)Haar特征
    目标检测的图像特征提取之(二)LBP特征
  • 原文地址:https://www.cnblogs.com/jiguixin/p/2270329.html
Copyright © 2011-2022 走看看