求数值在任意两个数字之内的任意N个数之和为任意数 。

求数值在任意两个数字之内的任意N个数之和为任意数

数值:1,2,3,4,5,6....48,49,50
取其中的任意5个数,但这5个数相加之和要等于100,并将所有这种组合罗列
例: 1+10+19+20+50=100
     3+14+16+27+40=100


原贴地址:http://community.csdn.net/Expert/topic/5362/5362401.xml?temp=.6463587     
                     http://community.csdn.net/Expert/topic/5370/5370928.xml?temp=.9533808


如果不求速度的话,该算法很容易,穷举就可以了,但如果数字够大,就完了了,所以要求速度
我给出的答案如下:

  1#include "stdafx.h"
  2#include "time.h"
  3#include <iostream>
  4#include "windows.h"
  5using namespace std;
  6
  7void printarray(int arr[], int length);
  8int cc = 0;
  9int circlecount = 0;
 10int othrercoutn = 0;
 11
 12//打印记录
 13void printarray(int arr[], int length);
 14//找出第一条满足条件的记录
 15bool GetFirstValue2(int num[], int imax, int isum, int ic);
 16
 17int _tmain(int argc, _TCHAR* argv[])
 18{
 19    int numcout = 5;
 20    int lower = 1;
 21    int upper = 50;
 22    int match_total_num = 100;
 23
 24    if (argc == 5)
 25    {
 26        sscanf(argv[1], "%d"&numcout); 
 27        sscanf(argv[2], "%d"&lower);
 28        sscanf(argv[3], "%d"&upper);
 29        sscanf(argv[4], "%d"&match_total_num);
 30    }

 31
 32    int * num = new int[numcout];
 33    //每一位变化时的初值
 34    int * minarr = new int[numcout * numcout];
 35    if (num == NULL || minarr == NULL)
 36    {
 37        cout << " 分配内存失败!" << endl;
 38        return 0;
 39    }

 40    
 41    memset(num, 0, numcout);
 42    memset(minarr, 0, numcout * numcout);
 43
 44    DWORD t3 = GetTickCount();
 45
 46    for(int i = lower; i < lower + numcout; i++)
 47    {
 48        *(num + i - lower) = i;
 49    }

 50
 51    GetFirstValue2(num, upper, match_total_num, numcout);
 52    for(int i = 0; i < numcout; i++)
 53    {
 54        for(int j = 0; j < numcout; j++)
 55        {
 56            *(minarr + i * numcout + j) = * (num + j);
 57        }

 58        //memcpy((minarr + (i * numcout)), num, numcout);
 59    }

 60    int iindex = numcout - 1;
 61    while(true)
 62    {
 63        //如果第一位比第二大并且当前位置是第一位就退出
 64        circlecount++;
 65        if (num[0+ 1 >= num[1- 1 && iindex == 0)
 66        {
 67            return 0;
 68        }

 69
 70        //如果后面一位小于前面一位,则再往前推进一位
 71        if (num[iindex] <= num[iindex - 1])
 72        {
 73            iindex--;
 74            for(int i = 0; i < numcout; i++)
 75            {
 76                *(num + i) = *(minarr + numcout *( iindex - 1+ i);
 77            }

 78            //memcpy(num,  (minarr +(iindex - 1) * numcout), numcout);
 79
 80            *(num + iindex - 1= *(num + iindex - 1+ 1;
 81            int iadd = 1;
 82            int m = 0;
 83            for(m = iindex - 1; m < numcout - 1; m++)
 84            {
 85                if (*(num + m) >= *(num++ 1- iadd)
 86                {
 87                    if (*(num + m + 1- * (num + m) <= 1)
 88                    {
 89                        othrercoutn++;
 90                        for(int i = iindex; i < numcout; i++)
 91                        {
 92                            *(num + i) = *(num + i - 1+ 1;
 93                        }

 94
 95                        if (GetFirstValue2(num, upper, match_total_num, numcout) == false)
 96                        {
 97                            DWORD t4 = GetTickCount();
 98                            cout << cc << "   " << t4 - t3 << endl;
 99                            cout << circlecount << "   " << othrercoutn << endl;
100                            //fclose(g_file);
101                            delete [] num;
102                            delete [] minarr;
103                            return 0;
104                        }

105                        break;
106                    }

107                    *(num + m + 1+= 1;
108                    iadd++;
109                }

110                else
111                {
112                    *(num ++ 1-= iadd;
113                    break;
114                }

115            }

116
117            if ( m == numcout - 1)
118            {
119                *(num + iindex) = 0;
120                continue;
121            }

122            if (*(num + iindex) > *(num + iindex - 1))
123            {
124                for(int i = iindex -1; i < numcout; i++)
125                {
126                    for(int j = 0; j < numcout; j++)
127                    {
128                        *(minarr + i * numcout + j) = *(num + j);
129                    }

130                }

131            }

132            continue;
133        }

134
135        cc++;
136        //printarray(num, numcout);
137        iindex = numcout - 1;
138        //后面减一,前面加一
139        *(num + iindex - 1+= 1;
140        *(num + iindex) -= 1;
141
142        if (cc == 452)
143        {
144            int i = 10;
145        }

146    }

147    return 0;
148}

149
150
151bool GetFirstValue2(int num[], int imax, int isum, int ic)
152{
153    int index = ic - 1;
154    while(true)
155    {
156        circlecount++;
157        if (index == 0 && num[index] == isum)
158        {
159            return false;
160        }

161
162        int isumtemp = 0;
163        forint i = 0; i < ic; i++)
164        {
165            isumtemp += num[i];
166        }

167
168        if (num[index] > imax || isumtemp > isum)
169        {
170            index--;
171            if (index < 0)
172            {
173                return false;
174            }

175            num[index] += 1;
176            for(int i = index + 1; i < ic; i++)
177            {
178                num[i] = num[i - 1+ 1;
179            }

180            continue;
181        }

182        else
183        {
184            if (isumtemp == isum)
185            {
186                return true;
187            }

188            num[ic - 1]++;
189            index = ic - 1;
190        }

191    }

192    return true;
193}

194
195void printarray(int arr[], int length)
196{
197    //fprintf(g_file, "%d", ++cc);
198    //fputs(": ", g_file);
199    //for(int i = 0; i < length; i++)
200    //{
201    //    fprintf(g_file, "%d", arr[i]);
202    //}
203    //fputs("\r\n", g_file);
204    
205    //cout << cc << ": ";
206    //for(int i = 0; i < length; i++)
207    //{
208    //    cout << arr[i] << ", ";
209    //}
210    //cout << endl;
211}

212




输入 mysum 6 1 300 600

输出

676440445(这个是组合个数)   21313(时间)
-1696061596   11408899

用简单循环算法找到第一个满足条件的记录
然后将某一位加一,某一位减一

posted on 2007-05-27 16:37  我的blog  阅读(282)  评论(0编辑  收藏  举报

导航