求数值在任意两个数字之内的任意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"
5
using namespace std;
6
7
void printarray(int arr[], int length);
8
int cc = 0;
9
int circlecount = 0;
10
int othrercoutn = 0;
11
12
//打印记录
13
void printarray(int arr[], int length);
14
//找出第一条满足条件的记录
15
bool GetFirstValue2(int num[], int imax, int isum, int ic);
16
17
int _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
151
bool 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
195
void 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
#include "stdafx.h"2
#include "time.h"3
#include <iostream>4
#include "windows.h"5
using namespace std;6

7
void printarray(int arr[], int length);8
int cc = 0;9
int circlecount = 0;10
int othrercoutn = 0;11

12
//打印记录13
void printarray(int arr[], int length);14
//找出第一条满足条件的记录15
bool GetFirstValue2(int num[], int imax, int isum, int ic);16

17
int _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
else111
{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

151
bool 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
else183
{184
if (isumtemp == isum)185
{186
return true;187
}188
num[ic - 1]++;189
index = ic - 1;190
}191
}192
return true;193
}194

195
void 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
用简单循环算法找到第一个满足条件的记录
然后将某一位加一,某一位减一


浙公网安备 33010602011771号