Subset Problem

来源:互联网 发布:apache shiro文档 编辑:程序博客网 时间:2024/04/29 21:04

2010年中兴面试题

编程题:

输入两个整数n和m,从数列1、2、3......n中随意取几个数,使得其和等于m,输出其中所有的组合和其组合数。


更加一般化的题目,一个有n个数的数组,假设这些数都为正数,且都不相等,找出这n个数中的任意几个数之和等于m的所有组合。

基本思想:回溯

以4个数为例,结合下图看程序。


#include <iostream>using namespace std; static int total_account;void swap(int *a, int *b){int t = *a;*a = *b;*b = t;}int partition(int a[], int left, int right){int pivot = a[right];int i = left-1;int j = right;for ( ; ; ){while (a[++i] < pivot){}while (a[--j] > pivot){if (j == left){break;}}if (i >= j){break;}swap(a[i], a[j]);}swap(a[i], a[right]);return i;}void QuickSort(int a[], int left, int right){if (left >= right){return ;}int pivot = partition(a, left, right);QuickSort(a, left, pivot-1);QuickSort(a, pivot+1, right);}void printSubset(int A[], int size){    for(int i = 0; i < size; i++)    {        cout<<A[i]<<"  ";    }    cout<<endl;} // inputs// s            - set vector// t            - tuplet vector// s_size       - set size// t_size       - tuplet size so far// sum          - sum so far// ite          - nodes count// target_sum   - sum to be foundvoid subset_sum(int s[], int t[],                int s_size, int t_size,                int sum, int ite,                const int target_sum){    if( target_sum == sum )    {total_account++;        printSubset(t, t_size);         // constraint check        if( ite + 1 < s_size && sum - s[ite] + s[ite+1] <= target_sum )        {            // Exclude previous added item and consider next candidate(回溯)            subset_sum(s, t, s_size, t_size-1, sum - s[ite], ite + 1, target_sum);        }        return;    }    else    {        // constraint check        if( ite < s_size && sum + s[ite] <= target_sum )        {            // generate nodes along the breadth            for( int i = ite; i < s_size; i++ )            {                t[t_size] = s[i];                 if( sum + s[i] <= target_sum )                {                    // consider next level node (along depth)                    subset_sum(s, t, s_size, t_size + 1, sum + s[i], i + 1, target_sum);                }            }        }    }} void generateSubsets(int s[], int size, int target_sum){    int *tuplet_vector = new int [size];     int total = 0;     QuickSort(s, 0, size-1);     for( int i = 0; i < size; i++ )    {        total += s[i];    }     if( s[0] <= target_sum && total >= target_sum )    {subset_sum(s, tuplet_vector, size, 0, 0, 0, target_sum);    } delete [] tuplet_vector;} int main(){    int weights[] = {15, 22, 14, 26, 32, 9, 16, 8};    int target = 53;    int size = sizeof(weights) / sizeof(weights[0]);     generateSubsets(weights, size, target); cout<<"组合数:"<<total_account<<endl; system("pause");    return 0;}