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 | } |