001
| // test5.2.cpp : 定义控制台应用程序的入口点。
|
002
| //
|
003
| // 2010.5.9
|
004
| //sylar
|
005
| //
|
006
| #include "stdafx.h"
|
007
| #include <iostream>
|
008
| using
namespace
std;
|
009
|
010
| //动态规划:0-1背包问题
|
011
| //bestValue[i][j]=max ( bestValue[i+1][j-w[i]]+v[i] ,bestValue[i+1][j] ) w[i]<=j
|
012
| //bestValue[i][j]=bestValue[i+1][j] w[i]>j
|
013
|
014
| class
Knapsack
|
015
| {
|
016
| private
:
|
017
|
int
*weight;
//物品重量数组
|
018
|
int
*value;
//物品价值数组
|
019
|
int
numOfItems;
//物品数量
|
020
|
int
bagSpace;
//背包容量
|
021
|
int
**bestValue;
//动态规划表格,记录bestValue[i][j]的价值,为最优价值,i表示物品i...n装入容量为j的背包能达到的最大价值
|
022
|
int
**path;
//为了求出取得最优值时的解,记录动态规划表不同表项的选择与否
|
023
| public
:
|
024
|
//构造函数
|
025
|
Knapsack(
int
numOfItems,
int
bagSpace)
|
026
|
{
|
027
|
weight=
new
int
[numOfItems+1];
|
028
|
value=
new
int
[numOfItems+1];
|
029
|
this
->bagSpace=bagSpace;
|
030
|
this
->numOfItems=numOfItems;
|
031
|
032
|
bestValue=
new
int
* [numOfItems+1];
|
033
|
for
(
int
i=0;i<numOfItems+1;i++)
|
034
|
{
|
035
|
bestValue[i]=
new
int
[bagSpace+1];
|
036
|
}
|
037
|
038
|
path=
new
int
* [numOfItems+1];
|
039
|
for
(
int
i=0;i<numOfItems+1;i++)
|
040
|
{
|
041
|
path[i]=
new
int
[bagSpace+1];
|
042
|
}
|
043
|
}
|
044
|
//输入物品的重量与价值
|
045
|
void
input()
|
046
|
{
|
047
|
int
i=1;
|
048
|
while
(i<=numOfItems)
|
049
|
{
|
050
|
cout<<
"输入第"
<<i<<
"个物品的重量"
<<endl;
|
051
|
cin>>weight[i];
|
052
|
cout<<
"输入第"
<<i<<
"个物品的价值"
<<endl;
|
053
|
cin>>value[i];
|
054
|
++i;
|
055
|
}
|
056
|
}
|
057
|
//动态规划核心算法
|
058
|
void
knapsack()
|
059
|
{
|
060
|
//初始化递归最底层,即将bestValue[n][0:c]进行初始化
|
061
|
for
(
int
i=0;i<=bagSpace;i++)
|
062
|
{
|
063
|
if
(weight[numOfItems]<=i)
|
064
|
{
|
065
|
bestValue[numOfItems][i]=value[numOfItems];
|
066
|
path[numOfItems][i]=1;
|
067
|
}
|
068
|
else
|
069
|
{
|
070
|
bestValue[numOfItems][i]=0;
|
071
|
path[numOfItems][i]=0;
|
072
|
}
|
073
|
}
|
074
|
//递推的进行动态规划,自底向上,最终bestValue[1][bageSpace]为1-n物品放入容量bagSpace内的最大价值
|
075
|
for
(
int
k=numOfItems-1;k>=1;k--)
|
076
|
{
|
077
|
for
(
int
j=0;j<=bagSpace;j++)
|
078
|
{
|
079
|
bestValue[k][j]=bestValue[k+1][j];
|
080
|
path[k][j]=0;
//不放入的情况
|
081
|
if
(weight[k]<=j)
//如果容量足够放入当前物品
|
082
|
{
|
083
|
if
(bestValue[k+1][j-weight[k]]+value[k]>bestValue[k][j])
//如果放入的价值大于不放的价值
|
084
|
{
|
085
|
bestValue[k][j]=bestValue[k+1][j-weight[k]]+value[k];
|
086
|
path[k][j]=1;
//那么就选择放入
|
087
|
}
|
088
|
}
|
089
|
}
|
090
|
}
|
091
|
}
|
092
|
//输出最大价值,并且输出选择方式
|
093
|
void
display()
|
094
|
{
|
095
|
//打印出bestValue[1][bagSpace],表示1...numOfItems的物品装入容量为bagSpace的最大价值
|
096
|
int
i=1;
|
097
|
int
j=bagSpace;
|
098
|
cout<<
"最大价值为"
<<bestValue[1][j]<<endl;
|
099
|
//根据path[1][bagSpace]的记录开始,递归到path[n][某容量],从而打印出每个物品是否被选择进入背包
|
100
|
while
(i<=numOfItems)
|
101
|
{
|
102
|
if
(path[i][j]==0)
//如果i物品没被放入,看i+1个物品装入容量j背包
|
103
|
{
|
104
|
++i;
|
105
|
}
|
106
|
else
|
107
|
{
|
108
|
cout<<
"<重量:"
<<weight[i]<<
",价值:"
<<value[i]<<
">"
<<endl;
|
109
|
j-=weight[i];
|
110
|
++i;
|
111
|
}
|
112
|
}
|
113
|
}
|
114
| };
|
115
|
116
| /*
|
117
| void main()
|
118
| {
|
119
|
Knapsack test(5,50);//5个物品,背包容量50
|
120
|
test.input();//输入5个物品的价值与重量
|
121
|
test.knapsack();//动态规划
|
122
|
test.display();//打印选择与最大价值
|
123
| }
|
124
| */
|
125
|
126
|
127
| //动态规划:0-1背包问题
|
128
| //bestValue[i][j]=max ( bestValue[i+1][j-w[i]]+v[i] ,bestValue[i+1][j] ) w[i]<=j
|
129
| //bestValue[i][j]=bestValue[i+1][j] w[i]>j
|
130
|
131
|
132
| /*
|
133
| 思路总结: 看到一个题目,首先看问什么,下面以此题举例分析一下。
|
134
|
135
| 0-1背包问题
|
136
|
137
| 1,问题要求什么?
|
138
| 答:求把n个物品放入容量C的背包内能达到的最大价值
|
139
|
140
| 2,转换成一个抽象一点的数学表达式是什么?
|
141
| 答:bestValue[n][C],表示n个物品放入容量C的背包的最大价值
|
142
|
143
| 3,不考虑算法应该怎么选择,我们实际去解决这个问题的时候,是从哪里开始去做的?
|
144
| 答:我们有n个物品,C容量背包。 于是我们开始解决问题,我先放第一个物品,如果能放进去,我就放进去,当然,我也可以不放。
|
145
| 第一个物品处理结束以后,我们着手于第二个物品,能放进去就放进去,当然,我们也可以不放。
|
146
| 所以,这就是一个决策问题,决策是从我们实际处理问题中抽象出来的,我们放物品的时候只能一个一个放,决策是放或者不放。
|
147
|
148
| 4,在决策了解的情况,我们应该考虑当前要求的bestValue[n][C],在决策放入或者不放入的情况,分别等于什么?
|
149
| 答:如果能够放入,那么我们的背包还有C-w[i], 物品还有n-1个,当然,我们也可以选择不放进去,那么我们背包依旧有C容量,物品还有n-1个。 所以我们修改一下我们对bestValue[n][C]的定义,从而就得到了一个最优子结构的递归公式。
|
150
|
151
| 为了我们决策的进行,即我们每次决策都是最第i个物品进行决策,所以bestValue[n][C]修改为best[i][C],表示i,i+1,i+2...n个物品放入容量为C的背包的最大价值。
|
152
|
153
| 所以:bestValue[i][j]=max ( bestValue[i+1][j-w[i]]+v[i] ,bestValue[i+1][j] ) w[i]<=j
|
154
| bestValue[i][j]=bestValue[i+1][j] w[i]>j
|
155
|
156
| 意思是:
|
157
| 如果当前容量j装不下物品i,那么i到n装入j的最大价值就等于i+1到n装入j的最大价值,就是公式的第二行。
|
158
| 如
果当前容量j可以装下物品i,那么我们可以装进去,当然,也可以犯贱,不装进去,看看结果如何,所以i到n个物品装入j容量背包的最大价值就等于
i+1到n物品装入j-w[i]容量的背包可以达到的最大价值+value[i]
,i+1到n物品装入j容量背包的最大价值,这两种不同决策的一个最大值。
|
159
|
160
| 总结:解决什么? 从哪里开始做起? 有哪些决策? 决策后会怎么样?
|
161
|
162
| 找
出了递归式,它具有最优子结构性质,即可以简单的理解为:当前的最优产生于子问题的最优,然后子问题的最优不受当前最优的影响,并且通过观察递归公式,应
该找到递归的最底层的i,j分别是什么,我们观察到i在逐渐增加,j在逐渐减小,所以我们在递推的时候,首先把最底层进行初始化,然后利用递归公式向上递
推。
所以我们需要首先初始化bestValue[n][0:C],即记录第n个物品装入0到C的背包的能达到的价值,当w[n]<=j
时,bestValue[n][j]等于value[n],如果w[n]>j,即容量不够,那么就是0.
|
163
|
164
| 我们能够从底向上递推的重要原因就是:最优子结构+无后效性 。 多多体会吧。 这是基础理解了。
|
165
|
166
| */
|
167
|
168
|
169
|
170
| #include <stdio.h>
|
171
| int
a[100],n,temp;
|
172
| void
QuickSort(
int
h,
int
t)
|
173
| {
|
174
|
if
(h>=t)
return
;
|
175
|
int
mid=(h+t)/2,i=h,j=t,x;
|
176
|
x=a[mid];
|
177
|
while
(1)
|
178
|
{
|
179
|
while
(a[i]<x) i++;
|
180
|
while
(a[j]>x) j--;
|
181
|
if
(i>=j)
break
;
|
182
|
temp=a[i];
|
183
|
a[i]=a[j];
|
184
|
a[j]=temp;
|
185
|
}
|
186
|
a[mid]=a[j];
|
187
|
a[j]=x;
|
188
|
QuickSort(h,j-1);
|
189
|
QuickSort(j+1,t);
|
190
|
return
;
|
191
| }
|
192
| /*
|
193
| int main()
|
194
| {
|
195
|
int i;
|
196
|
scanf("%d",&n);
|
197
|
for(i=0;i<n;i++) scanf("%d",&a[i]);
|
198
|
QuickSort(0,n-1);
|
199
|
for(i=0;i<n;i++) printf("%d ",a[i]);
|
200
|
return(0);
|
201
| }
|
202
| */
|
203
|
204
|
205
|
206
| #include "stdafx.h"
|
207
| #include<stdio.h>
|
208
| #include<math.h>
|
209
| #include <string.h>
|
210
| #include <iostream>
|
211
| using
namespace
std;
|
212
|
213
| /*
|
214
| //伪代码
|
215
| //
|
216
| if 等于 ' '
|
217
| {
|
218
| 直接输出5个
|
219
| }
|
220
| else if 不等于' '
|
221
| {
|
222
| if 这5个字符串是连续的
|
223
| {
|
224
| 直接输出这5个字符
|
225
| }
|
226
|
227
| if 这5个字符中含有' '
|
228
| {
|
229
| 只输出' '前面的几个字符
|
230
| }
|
231
| }
|
232
| */
|
233
|
234
| /*
|
235
| //有一个字符串,由字符和空格组成,输入一个每行最大字符数line_size,则按照每行line_size输出,不够则换行例如
|
236
| //输入 abcdef ghij kl mn opq r stxyzuvw line_size=5
|
237
| //输出
|
238
| abcde
|
239
| f
|
240
| ghij
|
241
| kl mn
|
242
| opq r
|
243
| stxyz
|
244
| uvw
|
245
| */
|
246
|
247
|
248
| int
fun1(
char
* str,
int
line_size)
|
249
| {
|
250
|
char
*p1;
|
251
|
char
* p2;
|
252
|
int
i;
|
253
|
p1=p2 =str;
|
254
|
int
flag = 0;
|
255
|
char
* out =
new
char
[line_size + 1];
|
256
|
for
(i = 0; i <
strlen
(str); i += line_size)
|
257
|
{
|
258
|
memset
(out,
'/0'
, line_size + 1);
|
259
|
if
( *(p1 + line_size) ==
' '
)
///////
|
260
|
{
|
261
|
p1 ++;
|
262
|
strncpy
(out, p1, line_size);
|
263
|
cout << out;
|
264
|
p1 = p1 + line_size;
|
265
|
cout<<endl;
|
266
|
}
|
267
|
else
|
268
|
{
|
269
|
p2 = p1 + line_size;
|
270
|
while
(*(--p2) !=
' '
&& p2 != p1);
|
271
|
if
(p1 == p2)
|
272
|
{
|
273
|
strncpy
(out, p1, line_size);
|
274
|
cout << out;
|
275
|
p1 = p1 + line_size;
|
276
|
cout<<endl;
|
277
|
continue
;
|
278
|
}
|
279
|
else
|
280
|
{
|
281
|
strncpy
(out, p1, p2 - p1);
|
282
|
cout << out;
|
283
|
p1 = p2;
|
284
|
cout<<endl;
|
285
|
continue
;
|
286
|
}
|
287
|
}
|
288
|
}
|
289
|
delete
[] out;
|
290
|
out = NULL;
|
291
|
return
1;
|
292
| }
|
293
|
294
| /*
|
295
| int main()
|
296
| {
|
297
| //关键:每5个判断一次,判断位置信息 如果为空,跳过,如果有数字 则计算
|
298
| char a[1024] = "abcdef ghij kl mn opq r stxyzuvw";
|
299
| // fun(a, 5);
|
300
| fun1(a, 5);
|
301
| return 1;
|
302
| }
|
303
| */
|
304
|
305
|
306
| //输入两个整数 n 和 m,从数列1,2,3.......n 中 随意取几个数,使其和等于 m ,要求将其中所有的可能组合列出来.编程求解
|
307
|
308
|
309
|
310
| //3)写出在母串中查找子串出现次数的代码.
|
311
| int
count1(
char
* str,
char
* s)
|
312
| {
|
313
|
char
*src = str;
|
314
|
char
*des = s;
|
315
|
int
times = 0;
|
316
|
while
( *src !=
'/0'
)
|
317
|
{
|
318
|
if
(*src == *des )
|
319
|
{
|
320
|
char
* temp1 = src;
|
321
|
char
* temp2 = des;
|
322
|
while
( *temp2 !=
'/0'
&& *(temp2++) == *(temp1++) );
|
323
|
if
(*temp2 ==
'/0'
)
//如果完全匹配
|
324
|
{
|
325
|
times++;
//出现次数加一
|
326
|
src +=
strlen
(s);
|
327
|
continue
;
|
328
|
}
|
329
|
}
|
330
|
src++;
//不匹配
|
331
|
}
|
332
|
return
times;
|
333
| }
|
334
|
335
| //2)写出二分查找的代码.
|
336
| int
|
337
| bfind(
int
* a,
int
len,
int
val)
|
338
| {
|
339
|
int
temp;
|
340
|
int
i,j;
|
341
|
i = 0; j = len - 1;
|
342
|
//if ()
|
343
|
while
(i <= j)
|
344
|
{
|
345
|
temp = (a[i] + a[j])/2;
|
346
|
if
(temp == val)
|
347
|
{
|
348
|
return
(i + j)/2;
|
349
|
}
|
350
|
else
if
(temp > val)
|
351
|
{
|
352
|
j = (i + j)/2 - 1 ;
|
353
|
}
|
354
|
else
if
(temp < val)
|
355
|
{
|
356
|
i = (i + j)/2 + 1 ;
|
357
|
}
|
358
|
}
|
359
|
return
-1;
|
360
| }
|
361
|
362
| //快速排序:
|
363
| void
quick_sort(
int
*x,
int
low,
int
high)
|
364
| {
|
365
|
int
i, j, t;
|
366
|
if
(low < high)
|
367
|
{
|
368
|
i = low;
|
369
|
j = high;
|
370
|
t = *(x+low);
|
371
|
while
(i<j)
|
372
|
{
|
373
|
while
(i<j && *(x+j)>t)
|
374
|
{
|
375
|
j--;
|
376
|
}
|
377
|
if
(i<j)
|
378
|
{
|
379
|
*(x+i) = *(x+j);
|
380
|
i++;
|
381
|
}
|
382
|
while
(i<j && *(x+i)<=t)
|
383
|
{
|
384
|
i++;
|
385
|
}
|
386
|
if
(i<j)
|
387
|
{
|
388
|
*(x+j) = *(x+i);
|
389
|
j--;
|
390
|
}
|
391
|
}
|
392
|
*(x+i) = t;
|
393
|
quick_sort(x,low,i-1);
|
394
|
quick_sort(x,i+1,high);
|
395
|
}
|
396
| }
|
397
| /*
|
398
| void main()
|
399
| {
|
400
|
int temp[] ={3,8,6,2,9,7,1};
|
401
|
quick_sort(temp, 0, 6);
|
402
| }
|
403
| */
|
404
|
405
| //快速排序:
|
406
| int
partition1(
int
* a,
int
begin,
int
end)
|
407
| {
|
408
|
int
value;
|
409
|
int
temp;
|
410
|
int
i, j;
|
411
|
int
pos;
|
412
|
value = a[begin];
|
413
|
j = end;
|
414
|
i = begin;
|
415
|
pos = begin;
|
416
|
if
(begin == end)
|
417
|
{
|
418
|
return
1;
|
419
|
}
|
420
|
while
(i < j)
|
421
|
{
|
422
|
while
(a[j] > value) j--;
|
423
|
while
(a[i] < value) i++;
|
424
|
425
|
temp = a[i];
|
426
|
a[i] = a[j];
|
427
|
a[j] = temp;
|
428
|
}
|
429
|
partition1(a, begin, i);
|
430
|
partition1(a, i, end);
|
431
|
return
1;
|
432
| }
|
433
|
434
| // max1(12, 8);
|
435
| int
max1(
int
m,
int
n)
|
436
| {
|
437
|
int
temp;
|
438
|
while
(m%n != 0)
|
439
|
{
|
440
|
temp = n;
|
441
|
n = m%n;
|
442
|
m = temp;
|
443
|
}
|
444
|
return
n;
|
445
| }
|
446
|
447
| //算法复杂度 m + n
|
448
| void
merge(
int
a[],
int
n,
int
b[],
int
m,
int
*c)
|
449
| {
|
450
|
int
i = 0;
|
451
|
int
j = 0;
|
452
|
int
k = 0;
|
453
|
while
(i < n && j < m)
|
454
|
{
|
455
|
if
(a[i] < b[j] && i < n)
|
456
|
{
|
457
|
c[k] = a[i];
|
458
|
i++;
|
459
|
}
|
460
|
else
if
(a[i] >= b[j] && j < m)
|
461
|
{
|
462
|
c[k] = b[i];
|
463
|
j++;
|
464
|
}
|
465
|
k++;
|
466
|
}
|
467
| }
|
468
|
469
| /*
|
470
| int main()
|
471
| {
|
472
|
473
| int str1[5] ={1,3,5,7,9};
|
474
| int str2[5] ={1,2,4,6,8};
|
475
| int out[30];
|
476
| merge(str1,5,str2,5,out);
|
477
| // char a[100] = "abcababaabc";
|
478
| // /char b[100] = "ab";
|
479
| // int num = count1(a, b);
|
480
|
481
| // int bf[10] = {1,2,3,4,5,6,7,8,9,10};
|
482
| // num = bfind(bf, 10, 10);
|
483
| int ttt = max1(20, 12);
|
484
|
485
| int a[10] = {4,6,8,1,3,5,7,9,2,10};
|
486
| partition1(a, 0 , 9);
|
487
|
488
| return 1;
|
489
| }
|
490
|
491
| */
|
492
|
493
|
494
|
495
|
496
| //栈(数组栈,指针栈)
|
497
| //来个简单的数组栈把
|
498
|
499
| template
<
class
T>
|
500
| class
xj_stack
|
501
| {
|
502
| public
:
|
503
|
xj_stack()
|
504
|
{
|
505
|
memset
(array, 0,
sizeof
(array));
|
506
|
totol_num = 0;
|
507
|
}
|
508
|
T pop_stack()
|
509
|
{
|
510
|
if
(totol_num == 0)
|
511
|
{
|
512
|
return
T(1);
|
513
|
}
|
514
|
return
array[--totol_num];
|
515
|
}
|
516
|
int
push_stack(T num)
|
517
|
{
|
518
|
array[totol_num++] = num;
|
519
|
return
1;
|
520
|
}
|
521
|
int
is_empty()
|
522
|
{
|
523
|
if
(totol_num==0)
|
524
|
{
|
525
|
return
1;
|
526
|
}
|
527
|
return
0;
|
528
|
}
|
529
| protected
:
|
530
| private
:
|
531
|
T array[30];
|
532
|
int
totol_num;
|
533
| };
|
534
|
535
| typedef
struct
_btree
|
536
| {
|
537
|
struct
_btree * left;
|
538
|
struct
_btree * right;
|
539
|
int
node_value;
|
540
| }btree, *pbtree;
|
541
|
542
| //建立一个二叉树
|
543
| //
|
544
| //
|
545
| int
create_ntree(pbtree& pnode)
|
546
| {
|
547
|
//pbtree pnode;
|
548
|
int
value;
|
549
|
cin>>value;
|
550
|
if
(value == 0)
|
551
|
{
|
552
|
return
0;
|
553
|
}
|
554
|
pnode =
new
btree;
|
555
|
memset
(pnode,
'/0'
,
sizeof
(btree));
|
556
|
pnode->node_value = value;
|
557
|
create_ntree(pnode->left);
|
558
|
create_ntree(pnode->right);
|
559
|
return
1;
|
560
| }
|
561
|
562
| //先序遍历一个二叉树,递归实现
|
563
| void
pre_order(pbtree root)
|
564
| {
|
565
|
if
(root == NULL)
|
566
|
{
|
567
|
return
;
|
568
|
}
|
569
|
cout<<root->node_value;
|
570
|
pre_order(root->left);
|
571
|
pre_order(root->right);
|
572
| }
|
573
|
574
| //先序遍历一个二叉树,非递归实现
|
575
| void
pre_order_ex1(pbtree root)
|
576
| {
|
577
|
xj_stack<pbtree> m_stack;
|
578
|
while
(root != NULL || m_stack.is_empty() != 1)
|
579
|
{
|
580
|
if
(root != NULL)
|
581
|
{
|
582
|
cout<<root->node_value;
|
583
|
m_stack.push_stack(root);
|
584
|
root = root->left;
|
585
|
}
|
586
|
else
|
587
|
{
|
588
|
root = m_stack.pop_stack();
|
589
|
root = root->right;
|
590
|
}
|
591
|
}
|
592
| }
|
593
|
594
| pbtree root = NULL;
|
595
| /*
|
596
| void main()
|
597
| {
|
598
|
create_ntree(root);
|
599
|
pre_order(root);
|
600
|
cout<<endl;
|
601
|
pre_order_ex1(root);
|
602
| }
|
603
| */
|
604
|
605
|
606
| //寻找第i小的数
|
607
| #include <iostream>
|
608
| using
namespace
std;
|
609
| const
int
N=10;
|
610
| int
partition(
int
*,
int
,
int
);
|
611
| void
exchange(
int
&,
int
&);
|
612
|
613
| int
find_mid_num(
int
*A,
int
p,
int
r,
int
i){
|
614
|
if
(p==r)
|
615
|
return
A[p];
|
616
|
int
q=partition(A, p, r);
|
617
|
int
k=q-p+1;
|
618
|
if
(k==i)
|
619
|
return
A[q];
|
620
|
else
if
(k<i)
|
621
|
return
find_mid_num(A, q+1,r,i-k);
|
622
|
else
|
623
|
return
find_mid_num(A, p, q-1, i);
|
624
| }
|
625
|
626
| int
partition(
int
*A,
int
p,
int
r){
|
627
|
int
x=A[r];
|
628
|
int
i=p-1;
|
629
|
for
(
int
j=p;j<r;j++)
|
630
|
if
(A[j]<=x)
|
631
|
{
|
632
|
i++;
|
633
|
exchange(A[j],A[i]);
|
634
|
}
|
635
|
exchange(A[i+1],A[r]);
|
636
|
return
i+1;
|
637
| }
|
638
|
639
| void
exchange(
int
&x,
int
&y)
|
640
| {
|
641
|
int
z=x;
|
642
|
x=y;
|
643
|
y=z;
|
644
| }
|
645
|
646
| int
main()
|
647
| {
|
648
|
int
Array[10]={1,4,5,3,8,7,5,9,6,2};
|
649
|
int
m=N/2;
|
650
|
int
output=find_mid_num(Array, 0, N-1, m);
|
651
|
cout << output << endl;
|
652
|
while
(1);
|
653
|
return
0;
|
654
| }
|