求数值在任意两个数字之内的任意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+m + 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 +m + 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 for( int 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
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+m + 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 +m + 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 for( int 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
用简单循环算法找到第一个满足条件的记录
然后将某一位加一,某一位减一