// test5.2.cpp : 定义控制台应用程序的入口点。 // // 2010.5.9 //sylar // #include "stdafx.h" #include <iostream> using namespace std; //动态规划:0-1背包问题 //bestValue[i][j]=max ( bestValue[i+1][j-w[i]]+v[i] ,bestValue[i+1][j] ) w[i]<=j //bestValue[i][j]=bestValue[i+1][j] w[i]>j class Knapsack { private: int *weight;//物品重量数组 int *value;//物品价值数组 int numOfItems;//物品数量 int bagSpace;//背包容量 int **bestValue;//动态规划表格,记录bestValue[i][j]的价值,为最优价值,i表示物品i...n装入容量为j的背包能达到的最大价值 int **path;//为了求出取得最优值时的解,记录动态规划表不同表项的选择与否 public: //构造函数 Knapsack(int numOfItems,int bagSpace) { weight=new int[numOfItems+1]; value=new int[numOfItems+1]; this->bagSpace=bagSpace; this->numOfItems=numOfItems; bestValue=new int* [numOfItems+1]; for(int i=0;i<numOfItems+1;i++) { bestValue[i]=new int[bagSpace+1]; } path=new int* [numOfItems+1]; for(int i=0;i<numOfItems+1;i++) { path[i]=new int[bagSpace+1]; } } //输入物品的重量与价值 void input() { int i=1; while(i<=numOfItems) { cout<<"输入第"<<i<<"个物品的重量"<<endl; cin>>weight[i]; cout<<"输入第"<<i<<"个物品的价值"<<endl; cin>>value[i]; ++i; } } //动态规划核心算法 void knapsack() { //初始化递归最底层,即将bestValue[n][0:c]进行初始化 for(int i=0;i<=bagSpace;i++) { if(weight[numOfItems]<=i) { bestValue[numOfItems][i]=value[numOfItems]; path[numOfItems][i]=1; } else { bestValue[numOfItems][i]=0; path[numOfItems][i]=0; } } //递推的进行动态规划,自底向上,最终bestValue[1][bageSpace]为1-n物品放入容量bagSpace内的最大价值 for(int k=numOfItems-1;k>=1;k--) { for(int j=0;j<=bagSpace;j++) { bestValue[k][j]=bestValue[k+1][j]; path[k][j]=0;//不放入的情况 if(weight[k]<=j)//如果容量足够放入当前物品 { if(bestValue[k+1][j-weight[k]]+value[k]>bestValue[k][j])//如果放入的价值大于不放的价值 { bestValue[k][j]=bestValue[k+1][j-weight[k]]+value[k]; path[k][j]=1;//那么就选择放入 } } } } } //输出最大价值,并且输出选择方式 void display() { //打印出bestValue[1][bagSpace],表示1...numOfItems的物品装入容量为bagSpace的最大价值 int i=1; int j=bagSpace; cout<<"最大价值为"<<bestValue[1][j]<<endl; //根据path[1][bagSpace]的记录开始,递归到path[n][某容量],从而打印出每个物品是否被选择进入背包 while(i<=numOfItems) { if(path[i][j]==0)//如果i物品没被放入,看i+1个物品装入容量j背包 { ++i; } else { cout<<"<重量:"<<weight[i]<<",价值:"<<value[i]<<">"<<endl; j-=weight[i]; ++i; } } } }; /* void main() { Knapsack test(5,50);//5个物品,背包容量50 test.input();//输入5个物品的价值与重量 test.knapsack();//动态规划 test.display();//打印选择与最大价值 } */ //动态规划:0-1背包问题 //bestValue[i][j]=max ( bestValue[i+1][j-w[i]]+v[i] ,bestValue[i+1][j] ) w[i]<=j //bestValue[i][j]=bestValue[i+1][j] w[i]>j /* 思路总结: 看到一个题目,首先看问什么,下面以此题举例分析一下。 0-1背包问题 1,问题要求什么? 答:求把n个物品放入容量C的背包内能达到的最大价值 2,转换成一个抽象一点的数学表达式是什么? 答:bestValue[n][C],表示n个物品放入容量C的背包的最大价值 3,不考虑算法应该怎么选择,我们实际去解决这个问题的时候,是从哪里开始去做的? 答:我们有n个物品,C容量背包。 于是我们开始解决问题,我先放第一个物品,如果能放进去,我就放进去,当然,我也可以不放。 第一个物品处理结束以后,我们着手于第二个物品,能放进去就放进去,当然,我们也可以不放。 所以,这就是一个决策问题,决策是从我们实际处理问题中抽象出来的,我们放物品的时候只能一个一个放,决策是放或者不放。 4,在决策了解的情况,我们应该考虑当前要求的bestValue[n][C],在决策放入或者不放入的情况,分别等于什么? 答:如果能够放入,那么我们的背包还有C-w[i], 物品还有n-1个,当然,我们也可以选择不放进去,那么我们背包依旧有C容量,物品还有n-1个。 所以我们修改一下我们对bestValue[n][C]的定义,从而就得到了一个最优子结构的递归公式。 为了我们决策的进行,即我们每次决策都是最第i个物品进行决策,所以bestValue[n][C]修改为best[i][C],表示i,i+1,i+2...n个物品放入容量为C的背包的最大价值。 所以:bestValue[i][j]=max ( bestValue[i+1][j-w[i]]+v[i] ,bestValue[i+1][j] ) w[i]<=j bestValue[i][j]=bestValue[i+1][j] w[i]>j 意思是: 如果当前容量j装不下物品i,那么i到n装入j的最大价值就等于i+1到n装入j的最大价值,就是公式的第二行。 如果当前容量j可以装下物品i,那么我们可以装进去,当然,也可以犯贱,不装进去,看看结果如何,所以i到n个物品装入j容量背包的最大价值就等于 i+1到n物品装入j-w[i]容量的背包可以达到的最大价值+value[i] ,i+1到n物品装入j容量背包的最大价值,这两种不同决策的一个最大值。 总结:解决什么? 从哪里开始做起? 有哪些决策? 决策后会怎么样? 找出了递归式,它具有最优子结构性质,即可以简单的理解为:当前的最优产生于子问题的最优,然后子问题的最优不受当前最优的影响,并且通过观察递归公式,应该找到递归的最底层的i,j分别是什么,我们观察到i在逐渐增加,j在逐渐减小,所以我们在递推的时候,首先把最底层进行初始化,然后利用递归公式向上递推。 所以我们需要首先初始化bestValue[n][0:C],即记录第n个物品装入0到C的背包的能达到的价值,当w[n]<=j时,bestValue[n][j]等于value[n],如果w[n]>j,即容量不够,那么就是0. 我们能够从底向上递推的重要原因就是:最优子结构+无后效性 。 多多体会吧。 这是基础理解了。 */ #include <stdio.h> int a[100],n,temp; void QuickSort(int h,int t) { if(h>=t) return; int mid=(h+t)/2,i=h,j=t,x; x=a[mid]; while(1) { while(a[i]<x) i++; while(a[j]>x) j--; if(i>=j) break; temp=a[i]; a[i]=a[j]; a[j]=temp; } a[mid]=a[j]; a[j]=x; QuickSort(h,j-1); QuickSort(j+1,t); return; } /* int main() { int i; scanf("%d",&n); for(i=0;i<n;i++) scanf("%d",&a[i]); QuickSort(0,n-1); for(i=0;i<n;i++) printf("%d ",a[i]); return(0); } */ #include "stdafx.h" #include<stdio.h> #include<math.h> #include <string.h> #include <iostream> using namespace std; /* //伪代码 // if 等于 ' ' { 直接输出5个 } else if 不等于' ' { if 这5个字符串是连续的 { 直接输出这5个字符 } if 这5个字符中含有' ' { 只输出' '前面的几个字符 } } */ /* //有一个字符串,由字符和空格组成,输入一个每行最大字符数line_size,则按照每行line_size输出,不够则换行例如 //输入 abcdef ghij kl mn opq r stxyzuvw line_size=5 //输出 abcde f ghij kl mn opq r stxyz uvw */ int fun1(char* str, int line_size) { char *p1; char* p2; int i; p1=p2 =str; int flag = 0; char* out = new char[line_size + 1]; for (i = 0; i < strlen(str); i += line_size) { memset(out, '\0', line_size + 1); if ( *(p1 + line_size) == ' ') /////// { p1 ++; strncpy(out, p1, line_size); cout << out; p1 = p1 + line_size; cout<<endl; } else { p2 = p1 + line_size; while (*(--p2) != ' ' && p2 != p1); if (p1 == p2) { strncpy(out, p1, line_size); cout << out; p1 = p1 + line_size; cout<<endl; continue; } else { strncpy(out, p1, p2 - p1); cout << out; p1 = p2; cout<<endl; continue; } } } delete [] out; out = NULL; return 1; } /* int main() { //关键:每5个判断一次,判断位置信息 如果为空,跳过,如果有数字 则计算 char a[1024] = "abcdef ghij kl mn opq r stxyzuvw"; // fun(a, 5); fun1(a, 5); return 1; } */ //输入两个整数 n 和 m,从数列1,2,3.......n 中 随意取几个数,使其和等于 m ,要求将其中所有的可能组合列出来.编程求解 //3)写出在母串中查找子串出现次数的代码. int count1(char* str,char* s) { char *src = str; char *des = s; int times = 0; while( *src != '\0') { if (*src == *des ) { char* temp1 = src; char* temp2 = des; while( *temp2 != '\0' && *(temp2++) == *(temp1++) ); if(*temp2 == '\0') //如果完全匹配 { times++; //出现次数加一 src += strlen(s); continue; } } src++; //不匹配 } return times; } //2)写出二分查找的代码. int bfind(int* a, int len, int val) { int temp; int i,j; i = 0; j = len - 1; //if () while (i <= j) { temp = (a[i] + a[j])/2; if (temp == val) { return (i + j)/2; } else if (temp > val) { j = (i + j)/2 - 1 ; } else if (temp < val) { i = (i + j)/2 + 1 ; } } return -1; } //快速排序: void quick_sort(int *x, int low, int high) { int i, j, t; if (low < high) { i = low; j = high; t = *(x+low); while (i<j) { while (i<j && *(x+j)>t) { j--; } if (i<j) { *(x+i) = *(x+j); i++; } while (i<j && *(x+i)<=t) { i++; } if (i<j) { *(x+j) = *(x+i); j--; } } *(x+i) = t; quick_sort(x,low,i-1); quick_sort(x,i+1,high); } } /* void main() { int temp[] ={3,8,6,2,9,7,1}; quick_sort(temp, 0, 6); } */ //快速排序: int partition1(int* a, int begin, int end) { int value; int temp; int i, j; int pos; value = a[begin]; j = end; i = begin; pos = begin; if (begin == end) { return 1; } while (i < j) { while (a[j] > value) j--; while (a[i] < value) i++; temp = a[i]; a[i] = a[j]; a[j] = temp; } partition1(a, begin, i); partition1(a, i, end); return 1; } // max1(12, 8); int max1(int m, int n) { int temp; while (m%n != 0) { temp = n; n = m%n; m = temp; } return n; } //算法复杂度 m + n void merge(int a[],int n,int b[],int m,int *c) { int i = 0; int j = 0; int k = 0; while (i < n && j < m) { if(a[i] < b[j] && i < n) { c[k] = a[i]; i++; } else if(a[i] >= b[j] && j < m) { c[k] = b[i]; j++; } k++; } } /* int main() { int str1[5] ={1,3,5,7,9}; int str2[5] ={1,2,4,6,8}; int out[30]; merge(str1,5,str2,5,out); // char a[100] = "abcababaabc"; // /char b[100] = "ab"; // int num = count1(a, b); // int bf[10] = {1,2,3,4,5,6,7,8,9,10}; // num = bfind(bf, 10, 10); int ttt = max1(20, 12); int a[10] = {4,6,8,1,3,5,7,9,2,10}; partition1(a, 0 , 9); return 1; } */ //栈(数组栈,指针栈) //来个简单的数组栈把 template<class T> class xj_stack { public: xj_stack() { memset(array, 0, sizeof(array)); totol_num = 0; } T pop_stack() { if (totol_num == 0) { return T(1); } return array[--totol_num]; } int push_stack(T num) { array[totol_num++] = num; return 1; } int is_empty() { if (totol_num==0) { return 1; } return 0; } protected: private: T array[30]; int totol_num; }; typedef struct _btree { struct _btree * left; struct _btree * right; int node_value; }btree, *pbtree; //建立一个二叉树 // // int create_ntree(pbtree& pnode) { //pbtree pnode; int value; cin>>value; if (value == 0) { return 0; } pnode = new btree; memset(pnode, '\0', sizeof(btree)); pnode->node_value = value; create_ntree(pnode->left); create_ntree(pnode->right); return 1; } //先序遍历一个二叉树,递归实现 void pre_order(pbtree root) { if (root == NULL) { return; } cout<<root->node_value; pre_order(root->left); pre_order(root->right); } //先序遍历一个二叉树,非递归实现 void pre_order_ex1(pbtree root) { xj_stack<pbtree> m_stack; while (root != NULL || m_stack.is_empty() != 1) { if (root != NULL) { cout<<root->node_value; m_stack.push_stack(root); root = root->left; } else { root = m_stack.pop_stack(); root = root->right; } } } pbtree root = NULL; /* void main() { create_ntree(root); pre_order(root); cout<<endl; pre_order_ex1(root); } */ //寻找第i小的数 #include <iostream> using namespace std; const int N=10; int partition(int *, int,int); void exchange(int &, int &); int find_mid_num(int *A, int p, int r, int i){ if (p==r) return A[p]; int q=partition(A, p, r); int k=q-p+1; if(k==i) return A[q]; else if(k<i) return find_mid_num(A, q+1,r,i-k); else return find_mid_num(A, p, q-1, i); } int partition(int *A, int p, int r){ int x=A[r]; int i=p-1; for(int j=p;j<r;j++) if(A[j]<=x) { i++; exchange(A[j],A[i]); } exchange(A[i+1],A[r]); return i+1; } void exchange(int &x, int &y) { int z=x; x=y; y=z; } int main() { int Array[10]={1,4,5,3,8,7,5,9,6,2}; int m=N/2; int output=find_mid_num(Array, 0, N-1, m); cout << output << endl; while(1); return 0; }