算法整理(分治法、贪心法、动态规…

来源:互联网 发布:javascript encodeuri 编辑:程序博客网 时间:2024/06/03 16:08

分治法:归并排序、快速排序、最大子段和 、最近点对问题

贪心法:多级调度问题、活动安排问题、背包问题

动态规划法:、最大子段和、近似串匹配、最优二叉树 、最长公共子序列、0-1背包问题、多段图最短路径

*******************************************************************

 分治法

 1、归并排序

 // Note:Your choice is C++ IDE

 //归并排序(分治法)

 #include<iostream>

 using namespace std;

 //合并两个有序子序列

 void Merge( int r1[ ] , int r[ ], int s, intm, int t)

     {

      inti,j,k;

         i=s; j=m+1; k=s;

        while (i<=m&& j<=t) { 

           if (r[i]<=r[j])r1[k++]=r[i++]; 

           else r1[k++]=r[j++];

        }

        if(i<=m) 

  while (i<=m) 

  r1[k++]=r[i++];

        else  

  while (j<=t)    

  r1[k++]=r[j++];

 

  for( i=s; i<=t; i++)

  r[i]=r1[i];   //r[]:第二个数组是合并排序后的序列

     }

    

 //分治法归并排序

 void MergeSort(int r[ ], int r1[ ], int s, intt) {

      intm;

       if (s==t) r1[s]=r[s];  

         else {

           m=(s+t)/2;

           MergeSort(r, r1, s, m);   //归并排序前半个子序列

           MergeSort(r, r1, m+1, t);  //归并排序后半个子序列

           Merge(r, r1, s, m, t);     //合并两个已排序的子序列

         }

     }

    

 int main()

 {

     intr[256],r1[256];

     intt;

    cin>>t;

     for(inti=1; i<=t; i++)

     cin>>r[i];

    

     ints=1;

    

    MergeSort( r,  r1, s,  t) ;

 

     for(i=1; i<=t; i++)

     cout<<r1[i]<<"";

     return0;

 }

 ===================================

 2、快速排序

 #include<iostream.h>

 

 void Swap(int a[], int m, int n){

     inttemp;

     temp=a[m];

  a[m]= a[n];

  a[n] =temp;

 }

 

 int Partition(int r[ ], int first, intend)

      {

        int   i=first ,j=end;        //初始化

          while(i<j)

          

       while (i<j&& r[i]<= r[j]) j--; //右侧扫描

              if (i<j){ 

                Swap(r,i,j);          //将较小记录交换到前面

                i++; 

              }

       while (i<j&& r[i]<= r[j]) i++; //左侧扫描

             if (i<j) {

              Swap(r,i,j);           //将较大记录交换到后面

               j--; 

             }

          }

          return i;   // i为轴值记录的最终位置

     }

 void QuickSort(int r[ ], int first, intend)

   {

      if(first<end) {     

        int pivot=Partition(r, first,end);  

        QuickSort(r, first,pivot-1); 

        QuickSort(r, pivot+1,end);

      }

   }

 

 void main(){

   int n,r[100],i;

  cin>>n;

   for( i=1;i<=n; i++)

  cin>>r[i];

    QuickSort(r,0,n);

    for( i=1;i<=n; i++)

 cout<<r[i]<<"";

 }

 

 ===========================================

 3、最大子段和 

 一、蛮力法

 #include<iostream.h>

 int BFMaxSum(int a[ ], int n){

       int sum=0, i,j;  

    for(i=0;i<n; i++){

    int s1=0;  //s1的复原为零很重要;

    for(j=i;j<n; j++){

  s1 += a[j];

  if (s1 > sum)  sum = s1;

     //cout<<j<<""<<sum<<""<<endl; //这是自己的调试过程 

    }

    }

  return sum;

 }

 void main(){ 

   int a[100];

   int i,n;

 cout<<"请输入整数个数:";

  cin>>n;

  cout<<"请输入这"<<n<<"个整数所组成的序列:";

   for(i=0;i<n; i++)

   cin>> a[i];

   int rs=BFMaxSum( a, n);

  cout<<"该序列的最大字段和为:"<<rs<<endl;

 }

 

 二、分治法

 #include<iostream.h>

 int MaxSubSum(int a[ ], int left, int right){

       int sum=0,i,j;

       //如果序列长度为1,直接求解

       if (left==right) {     

           if(a[left]>0)   sum=a[left];

           else  sum=0;

       }

      else {

         int center=(left+right)/2;   //划分

          intleftsum=MaxSubSum(a, left, center); 

          intrightsum=MaxSubSum(a, center+1, right);  

  

          //以下对应情况③,先求解s1     

         int   s1=0,lefts=0;           

        for (i=center;i>=left; i--){

           lefts+=a[i];

           if (lefts>s1) s1=lefts;

        }

       int  s2=0, rights=0;          //再求解s2

       for (j=center+1; j<=right;j++){ 

           rights+=a[j];

           if (rights>s2) s2=rights;

        }

        sum=s1+s2;           //计算情况③的最大子段和 

       //合并,在sum、leftsum和rightsum中取较大者

        if(sum<leftsum) sum=leftsum;                  

        if(sum<rightsum) sum=rightsum;

      }

      returnsum;

 }

 void main(){

   int a[100];

   int i,n;

  cout<<"请输入整数个数:";

  cin>>n;

  cout<<"请输入这"<<n<<"个整数所组成的序列:";

   for(i=0;i<n; i++)

   cin>> a[i];

   int rs=MaxSubSum( a, 0, n-1);

  cout<<"该序列的最大字段和为:"<<rs<<endl;

 }

 

 三、动态规划法

 参考动态规划法中的。。

 ==============================================================

 4、最近点对问题

 一、参考

 #define inf 9999999

 #include<stdio.h>

 #include<math.h>

 #include<algorithm>

 using namespace std;

 struct point

 {

     double x, y;

 }p[100005];

 int a[100005];   //保存筛选的坐标点的索引

 

 bool cmpx( point a , point b){   //结构体数组的排序//这里用的是下标索引

     returna.x < b.x;

 }

 bool cmpy(int a , int b){

     returnp[a].y < p[b].y;

 }

 

 double dis(point a , point b){

     returnsqrt( (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y));

 }

 double min(double a , double b){

     return a< b ? a : b;

 }

 

 double closest(int low , int high)

 {

    if(low==high)

     returninf;   //1、如果n=1,返回无限大值

     int mid= (low + high)>>1;  //除2操作可为右移一位;  2、得到中点数

     doubleans = min( closest(low , mid) , closest(mid + 1 , high) ); //分治法

 

     int i ,j , cnt = 0;

     for(i =low ; i <= high ; ++i)

     {

        if(p[i].x >=p[mid].x - ans && p[i].x<= p[mid].x + ans)

           a[cnt++] = i;  //a[]数组记录点的坐标

     }

  sort(a , a + cnt , cmpy);

     for(i =0 ; i < cnt ; ++i)

     {

        for(j = i+1 ; j<cnt&&j<=i+7 ;++j)

        {

           if(p[a[j]].y - p[a[i]].y >=ans)

               break;

           ans = min(ans , dis(p[a[i]] , p[a[j]]));

        }

     }

     returnans;

 }

 int main()

 {

     inti,n;

    while(scanf("%d",&n) != EOF)

     {

        if(!n)

           break;

        for(i = 0 ; i <n ; ++i)

           scanf("%lf%lf",&p[i].x,&p[i].y);

        sort(p , p + n , cmpx);

        printf("%.2lf\n",closest(0 , n- 1));

     }

     return0;

 }

 

 二、蛮力法

 #include<iostream>

 using namespace std;

 int main()

 {

     intn,i,j,x[256],y[256],index1=0,index2=0;

     intd,min;

    cin>>n;

     for(i=0;i<n; i++)

     cin>>x[i]>>y[i];

 

    //先假定第一个和第二个点间的距离为所有点对的距离的最小值

    min=(x[1]-x[2])*(x[1]-x[2])+(y[1]-y[2])*(y[1]-y[2]);

 

    //为了避免同一对点计算两次,只考虑i<j的那些点对

     for(i=0;i<n; i++)

     for(j=i+1; j<n; j++){

     //d为点对间的距离,运用打擂台的思想

     d=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);

     //index1,index2记录点对

     //min即为最后所有点对间的最小距离值

     if(d<=min){

     min=d;

     index1=i+1;

     index2=j+1;

      }

      }

     cout<<"距离最短的两个点是第"<<index1<<"个点与第"<<index2<<"个点"<<endl; 

     cout<<"最近的距离的平方是"<<min<<endl;

     return0;

 }

 三、分治法

   与最大子段和的分治法很相像

 #include<iostream>

 //#include<cstdlib>

 #include<cmath>

 #define Max 10000000

 using namespace std;

 int min(int a,int b){   //求两数最小值

  return  (a>=b ) ? b : a;

 }

 int abs(int a){    //绝对值

  return a>0? a: -a;

 }

 int dis(int x1, int y1, int x2, int y2){//距离

 cout<<"计算的距离:"<<x1<<","<<y1<<"与"<<x2<<","<<y2<<endl;

  return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);

 }

 

 int ClosePoints(int n,int s[][2]){ //用二维数组存放点的横纵坐标

  //1、点的个数应该大于2

  if (n < 2) return Max;

  if(n==2) returndis(s[0][0],s[0][1],s[1][0],s[1][1]);

 

     intm=0,i,j;

     ints1[256][2],s2[256][2];

      

    //2、m为s中x坐标的中位数

    sort(s,s+n);

  m=(s[0]+s[n-1])/2;

    // for(i=0;i<n; i++){

      // m += s[i][0];

   //cout<<"s:"<<s[i][0]<<""<<s[i][1]<<endl;

     //}

     //m /=n;

     

  //3、构造s1和s2, 使得s1中的x坐标小于m,s2中点的坐标大于m

  int k=0;

  int h=0;

  for(i=0;i<n; i++)

  {

  if(s[i][0]<m)

  {

  s1[h][0]=s[i][0];

  s1[h++][1]=s[i][1];

  }

  else

  {

  s2[k][0]=s[i][0];

  s2[k++][1]=s[i][1];

  }

  }

     

  //4、分治法

  cout<<endl;

  int d1=ClosePoints(h,s1);

  int d2=ClosePoints(k,s2);

  

  //5、使得d为S1中的最近距离d1和S2中的最近距离d2的最小值

  int d=min(d1,d2);

 

 //6、构造p1和p2,使得p1是s1中点的x坐标与m的距离小于d的点集,p2是s2中点的x坐标与m的距离小于d的点集 

  int c=0,f=0;

  int p1[256][2],p2[256][2];

 

  for(i=0; i<h; i++)

  {

  if(abs(s1[i][0]-m)<d){

  for(j=0; j<2; j++)

  p1[c++][j]=s1[i][j];  

  }

  //输出s1数组

  cout<<"s1:"<<s1[i][0]<<""<<s1[i][1]<<endl;

  }

  for(i=0; i<k; i++)

  {

  if(abs(s2[i][0]-m)<d){

  for(j=0; j<2; j++)

  p2[f++][j]=s2[i][j];

  }

  //输出s2数组

  cout<<"s2:"<<s2[i][0]<<""<<s2[i][1]<<endl;

  }

 

  //7、将p1和p2中点的按y坐标升序排列   

  int temp;

  for(i=0; i<c; i++)

  for(j=1; j<c-i; j++){

  if(p1[j-1][1]>p1[j][1]){

  temp=p1[j][1];

  p1[j][1] = p1[j-1][1];

  p1[j+1][1] = temp;

 

  temp=p1[j][0];

  p1[j][0] = p1[j-1][0];

  p1[j+1][0] = temp;

  }       

  }

  //输出排序后的p1数组

  for(i=0; i<c; i++)

  cout<<"p1:"<<p1[i][0]<<""<<p1[i][1]<<endl;

  

  for(i=0; i<f; i++)

  for(j=1; j<f-i; j++){

  if(p2[j-1][1]>p2[j][1]){

  temp=p2[j][1];

  p2[j][1] = p2[j-1][1];

  p2[j+1][1] = temp;

 

  temp=p2[j][0];

  p2[j][0] = p2[j-1][0];

  p2[j+1][0] = temp;

  }       

  }

    //输出排序后的p2数组

  for(i=0; i<f; i++)

  cout<<"p2:"<<p2[i][0]<<""<<p2[i][1]<<endl;

    cout<<endl;

 

 //8、对p1中的每一个点p,在p2中查找与点p的y坐标小于d的点,并求出其中的最小距离dmin

  int dmin=0;

  if(c!=0 &&f!=0)

 dmin=dis(p1[0][0],p1[0][1],p2[0][0],p2[0][1]);

  else return min(d,Max);

 

  for(i=0; i<c; i++){

  for(j=0; j<f; j++){

  if( abs(p1[i][1]-p2[j][1])<d){

  dmin = dis(p1[i][0], p1[i][1], p2[j][0],p2[j][1]);

  d=dmin;

  }

  }

  }

  //9、返回最小值d

      returnmin(d,dmin);     

 }

  

 int main()

 {

  int s[256][2];

  int n,i,j;

  cin>>n;

    //依次输入n个点的x,y坐标

     for(i=0;i<n; i++)

  for(j=0; j<2; j++)

 cin>>s[i][j];

    

     int rd=ClosePoints(n,s);

    

    cout<<"最近点对间的距离为:";

 cout<<sqrt(rd)<<endl;

 

     return0;

 }

 ==============================

 ******************************************

 贪心法

 1、多级调度问题

 #include<iostream>

 #include<iostream>

 #include<cstdio>

 #include<algorithm>

 using namespace std;

 struct Data

  {

      intdata;

     intindex;

  };

 Data t[100];

 Data d[100];

 bool cmp(Data a,Data b){ //实现结构体数组按照data项进行从大到小排序

  return a.data > b.data ;

 }   

 int  sortmin(Data d[], intn){  //寻找d[]数组中的最小值

  int i,indexs=0;

  for(i=0; i<n; i++){

  if(d[i].data < d[indexs].data)

  indexs=i;

  }

  return indexs;

 }

 void duoji(Data t[],  int n,int m){

  int i,  S[100][100], p[100] ,  h[100];

  Data d[100];

  memset(h,0,sizeof(h));

 

  sort(t,t+n,cmp);  //结构体的排序

 cout<<endl<<"排序后的作业序号为:";

  for(i=0; i<n; i++){

  p[i]=t[i].index; //1、将t[]排序后,按照从大到小将作业号存储在p[]数组中

    cout<<p[i]+1<<"";

  }

  cout<<endl;

 for(i=0; i<m; i++){ //2、初始化d[]数组,d[]数组记录的是m台机器的空闲时间

  d[i].data=0;

  d[i].index=i;

  }

 

  if(n<m){   //A、当作业数n < 机器数m的情况

  for(i=0; i<n; i++){ //记录第一次的分配

  S[i][0]=p[i] ;  

  d[i].data = t[i].data ;

 cout<<"第"<<i<<"台机器处理的作业号为:"<<S[i][0]<<"; "

  <<"所需时间分别为:"<<d[i].data<<endl;

  }

 }

  else{  //B、当作业数n> 机器数m的情况

  for(i=0; i<m; i++){ //记录第一次的分配

  S[i][0]=p[i] ;  

  d[i].data = t[i].data ;

 cout<<"第"<<i+1<<"台机器处理的作业号为:"<<S[i][0]<<"; "

  <<"所需时间为:"<<d[i].data<<endl;

  }

  for(i=m; i<n; i++){

  int j=sortmin(d,m);

  cout<<"下一次为机器"<<j+1<<"来处理作业";  //j验证第一次是正确的

  S[j][++h[j]]=p[i];

  cout<<" ,并且此次机器"<<j+1<<"处理的作业为:"<<S[j][h[j]]+1<<"";

  d[j].data += t[i].data;

  cout<<endl;

  }

 }

 }

 int main()

 {

     inti,n,m;

    cout<<"输入作业个数n和机器个数m:";

    cin>>n>>m;

    cout<<"输入完成各作业所需要的处理时间:"<<endl;

     for(i=0;i<n; i++){

    cin>>t[i].data;

    t[i].index=i;

     }

    cout<<endl<<"各机器所处理的作业情况为:"<<endl;

    cout<<endl;

     duoji(t, n,  m);      

     return0;

 }

 ====================================================

 2、活动安排问题

 4

 1 4

 3 5

 0 6

 5 7

 #include<iostream.h>

 #include<algorithm>

 using namespace std;

 struct Data{

    int s,f;

 }time[100];

 

 bool cmp(Data a, Data b){

   return a.f<=b.f;

 }

 

 void ActiveManage(Data time[], bool a[ ], intn)

     //各活动的起始时间和结束时间存储于数组s和f中且

       //按结束时间的非减序排列 

  sort(time+1, time+n+1, cmp);

  int i,j,count, rode[100],k=1; 

    a[1]=1;

     j=1;count=1; rode[1]=1;

     for(i=2; i<=n; i++) //从 活动i 开始寻找与 活动j 相容的活动,j从1开始,如此循环贪心寻找

        

           if (time[i].s >= time[j].f ) {

             a[i]=1;

             j=i;

   rode[++k]=i;

             count++;

           }

           elsea[i]=0;

        }

  cout<<"共有"<<count<<"个活动,它们分别是:"<<endl;

        for(i=1; i<=k;i++)

       cout<<"活动:"<<rode[i]<<""<<endl;

 }

 

 void main(){

  int n,i;

  bool a[100];

  cin>>n;

  for(i=1; i<=n; i++)

    cin>>time[i].s>>time[i].f;

 

   ActiveManage(time,a,n);

 }

 ===================================

 3、背包问题

 3

 20 30 10

 60 120 50

 50

 #include<iostream>

 #include<algorithm>

 using namespace std;

 struct Data

  {

      floatdata;

      intindex;

  };

  Data origData[100];

 

  bool cmp(Data a, Data b){

   returna.data>b.data;

  }

 float Bag(float w[],float v[],float C,intn){

  int i,x[100];

  float vsum=0;

  float r[100], w1[100], v1[100];

  for(i=1; i<=n; i++)

  r[i]=v[i]/w[i];

     

  for ( i=1; i<=n; i++){  //初始化OrigData[]数组,记录v[i]/w[i]

     origData[i].data = r[i];

     origData[i].index = i;

  }

  sort(origData+1,origData+n+1,cmp); //排列OrigData[]数组   又是下标的问题

 

  for(i=1; i<=n; i++){    //根据v[i]/w[i]的降序排列重排列w[]和v[]

  w1[i]=w[origData[i].index];

  v1[i]=v[origData[i].index];

  }

  

   memset(x,0 ,sizeof(x));

    i=1; 

  while(w1[i]<=C){

  origData[i].data=1;

  C -= w1[i];

  vsum +=v1[i];

  i++;

  }

    origData[i].data = C/w1[i];

  vsum += v1[i] * origData[i].data;  //此处纠结了好久。。。

 cout<<"所选物品及百分比为:(1代表全选,0代表不选)"<<endl;

  for(int j=1; j<=i; j++)

 cout<<origData[j].data<<"";

  cout<<endl;

  return vsum; 

 }

 void  main(){

    int n,i,j;

    float vsum=0;

     floatw[100],v[100],C;

    cout<<"输入物品的数量:";

    cin>>n;

    cout<<"输入这"<<n<<"个物品的重量:"<<endl;

     for(i=1;i<=n; i++)

    cin>>w[i]; 

     cout<<"输入这"<<n<<"个物品的价值:"<<endl;

     for(j=1;j<=n; j++)

    cin>>v[j];

    cout<<"输入背包容量C:"<<endl;

    cin>>C; 

 

     floatrs=Bag(w,v,C,n);

    cout<<"背包中的物品最大价值容量为:"<<rs<<endl;   

 }

 =============================================

 **********************************************

 动态规划法

 1、最大子段和

 #include<iostream.h>

 #include<algorithm>

 using namespace std;

 //数列b[]代表前j个数的最大子段和(是加上a[j]的值)

 int DPMaxSum(int a[ ], int n){

       int j,b[100];

       b[1]=a[1];  //下标为1到n 

 

    for(j=2;j<=n; j++){

  if(b[j-1]>0)  b[j]=b[j-1]+a[j];

  else   b[j] = a[j];

    }

 

    sort(b+1,b+n+1);//注意数组与此处排序函数的一致性

                      -------------------------(还有一个递推式)

    return b[n];

 }

 void main(){

   int a[100];

   int i,n;

  cout<<"请输入整数个数:";

  cin>>n;

  cout<<"请输入这"<<n<<"个整数所组成的序列:";

   for(i=1;i<=n; i++)

   cin>> a[i];

   int rs=DPMaxSum(a, n); 

  cout<<"该序列的最大字段和为:"<<rs<<endl;

 }

 =================================================

 2、近似串匹配

 5 14 1

 happy

 Have a hsppy day!

 //-----唯一的问题是不识别空格符

 #include<iostream.h>

 int min(int a,int b,int c){

  int min=a;

  if(a>=b) min =b;

  if(min >=c) min=c;

  return min;

 }

 //P[m]数组存放输入的样本,T[n]数组存放匹配的文本, K-近似匹配

 //D[i][j]数组存放样本P前缀p1到pi与文本T前缀T1到Tj的最小差别数

 int ASM(char P[ ], char T[ ], int m, int n,int K){

  int j,i, D[100][100];

         for (j=1;j<=n; j++)   //初始化第0行

         D[0][j]=0;

         for (i=0;i<=m; i++)   //初始化第0列

           D[i][0]=i;

         for (j=1;j<=n; j++)   //根据递推式依次计算每一列

        {

           for (i=1; i<=m; i++)

           {

               if (P[i]==T[j] ) 

                  D[i][j]= min( D[i-1][j-1],D[i-1][j]+1, D[i][j-1]+1);

               else

                  D[i][j]=min( D[i-1][j-1]+1,D[i-1][j]+1, D[i][j-1]+1);

           }

           if ( D[m][j]<=K) return j;//输出匹配末位置

         }

     }

 void main(){

  char P[100], T[100];

   int i,m,n,K;

  cout<<"请输入样本字符数m,文本字符数n和 K值:"<<endl;

  cin>>m>>n>>K;

  cout<<"请输入样本字符串和文本字符串:"<<endl;

   for(i=1;i<=m; i++)

  cin>>P[i];

   for(i=1;i<=n; i++)

  cin>>T[i];  

  cout<<"最大匹配数是:"<<ASM(P,T,m,n,K)<<endl;

 }

 ====================================================

 3、最优二叉树       

 请输入字符个数n:

 4

 请输入字符的查找概率

 0.1 0.2 0.4 0.3

 最优二叉查找树的平均比较次数是:1.7

 Press any key to continue

 

 #include<iostream.h>

 #define MAX 999

 //数组p[]存放n个字符的查找概率

 //数组C[i][j]是二叉查找树T(i,j)的平均比较次数

 //数组R[i][j]是二叉查找树T(i,j)的根节点序号

 double OptimalBST( int n, double p[100 ],double C[100 ][100 ], int R[ 100][100 ] ){

  int i,j,d;

  for (i=1; i<=n; i++) {  //初始化

         C[i][i-1]=0;

         C[i][i]=p[i];

         R[i][i]=i;

       }

       C[n+1][n]=0;

    for (d=1;d<n; d++)    //按对角线逐条计算

     for(i=1; i<=n-d; i++){

         j=i+d;

  double min, sum;

  int mink;  

        min=MAX; mink=i; sum=0;

        for (int k=i;k<=j; k++){

          sum=sum+p[k];

           if(C[i][k-1]+C[k+1][j]<min) {

             min=C[i][k-1]+C[k+1][j];

             mink=k;

           }

        }

        C[i][j]=min+sum;

        R[i][j]=mink;

      }

      returnC[1][n];

 }

 

 void main(){

   int i, R[100][100] ,n ;

   doubleP[100],C[100][100];

  cout<<"请输入字符个数n:"<<endl;

  cin>>n;

  cout<<"请输入字符的查找概率"<<endl;

   for(i=1;i<=n; i++)

   cin>>P[i];

  cout<<"最优二叉查找树的平均比较次数是:"<<OptimalBST(n,P, C ,R)<<endl;

 }

 =========================================

 4、最长公共子序列

 

 输入两个序列的个数m,n:

 6 9

 a b c b d b

 a c b b a b d b b

 最长公共子序列是:a c b d b

 最长公共子序列的长度是:5

 Press any key to continue

 

 #include<iostream.h>

 //L[i][j]为序列x[i]与y[j]序列的最长公共子序列的长度

 //S[][]记录三种状态,回溯最长公共子序列

 int CommonOrder(int m, int n, char x[ ], chary[ ], char z[]){

  int L[100][100],i,j,k,S[100][100];

      for (j=0; j<=n; j++)  //初始化第0行

         L[0][j]=0;

      for (i=0; j<=m; i++)  //初始化第0列

         L[i][0]=0;

 

      for (i=1; i<=m; i++)

         for (j=1;j<=n; j++)

           if (x[i]==y[j]) { 

  L[i][j]= L[i-1][j-1]+1; 

  S[i][j] = 1; 

  }

           else if(L[i][j-1] >= L[i-1][j]) { 

    L[i][j] =L[i][j-1]; 

   S[i][j]=2; 

    }

          else {

  L[i][j]=L[i-1][j]; 

  S[i][j]=3; 

   }

  cout<<"最长公共子序列是:";

       i=m; j=n; k=L[m][n];

      while (i>0&& j>0) {

         if (S[i][j]==1){ 

  z[k]=x[i]; 

  k--; i--; j--; 

  }

        else if (S[i][j]==2) j--;

          elsei--;

      }

   for(i=1;i<=L[m][n]; i++)

  cout<<z[i]<<"";

  cout<<endl;

      returnL[m][n];

   }

 void main(){

     charx[100],y[100],z[100];

  int n,m;

 cout<<"输入两个序列的个数m,n:"<<endl;

 cin>>m>>n;

  for(int i=1; i<=m; i++)

  cin>>x[i];

  for(i=1; i<=n; i++)

  cin>>y[i];

  cout<<"最长公共子序列的长度是:"<<CommonOrder(m,n,x,y,z)<<endl;

 }

 ======================================

 5、0-1背包问题

 输入物品数量:

 3

 输入这3个物品的重量:

 20 30 10

 输入这3个物品的价值:

 60 120 50

 输入背包容量C:

 50

 输出装入背包的物品:1表示装入,0表示未装入

 1 1 0

 背包中的物品最大价值容量为:180

 Press any key to continue

 

 #include<iostream.h>

 int max(int a,int b){

 return a>b ? a : b;

 }

 //V[i][j]表示在前i个物品中能够装入容量为j的背包中的物品的价值最大值

 //V[i][0] , V[0][j]都为0;

 int KnapSack(int n, int w[ ], int v[ ],int C){     //n个物品,C为最大容量

     inti,j;

     intV[100][100],x[100];

 

      for(i=0; i<=n; i++)   //初始化第0列

       V[i][0]=0;

      for(j=0; j<=C; j++)   //初始化第0行

       V[0][j]=0;

 

      for(i=1; i<=n; i++)  //计算第i行,进行第i次迭代

       for (j=1; j<=C; j++)

          if(j<w[i])   //第i个物品不能装入(超重)

         V[i][j]=V[i-1][j];

         else     //满足装入条件(装入后未超重),但也可不装

  V[i][j]=max(V[i-1][j], V[i-1][j-w[i]]+v[i]); //装或者不装后的价值的最大值

 

  //求装入背包的物品:1表示装入,0表示未装入

     j=C;  

     for(i=n; i>0; i--){

        if(V[i][j]>V[i-1][j]) {

          x[i]=1;

         j=j-w[i];

  }

       else x[i]=0;

 }

  //输出装入背包的物品:1表示装入,0表示未装入

    cout<<"输出装入背包的物品:1表示装入,0表示未装入"<<endl;

  for(i=1; i<=n; i++)

 cout<<x[i]<<"";

  cout<<endl;

  

  return V[n][C];   //返回背包取得的最大价值

 }

 int main(){

     intn,i,j,w[100],v[100],C;

    cout<<"输入物品数量:"<<endl;

    cin>>n;

 cout<<"输入这"<<n<<"个物品的重量:"<<endl;

     for(i=1;i<=n; i++)

    cin>>w[i];

 cout<<"输入这"<<n<<"个物品的价值:"<<endl;

     for(j=1;j<=n; j++)

    cin>>v[j];

 cout<<"输入背包容量C:"<<endl;

    cin>>C;

 

    cout<<"背包中的物品最大价值容量为:"<<KnapSack(n, w, v,C)<<endl;

     return0;

 }

 ========================================

 6、多段图最短路径

 输入城市个数:10

 输入城市之间的距离:

 100 4 2 3 100 100 100 100 100 100

 100 100 100 100 9 8 100 100 100 100

 100 100 100 100 6 7 8 100 100 100

 100 100 100 100 100 4 7 100 100 100

 100 100 100 100 100 100 100 5 6 100

 100 100 100 100 100 100 100 8 6 100

 100 100 100 100 100 100 100 6 5 100

 100 100 100 100 100 100 100 100 100 7

 100 100 100 100 100 100 100 100 100 3

 100 100 100 100 100 100 100 100 100 100

 最短路径长为:16

 最短路径为:0->3->5->8->9

 Press any key to continue

 

 #include<iostream.h>

 //cost[i]表示从顶点i到顶点n-1 的最短路径

 //path[i]表示从顶点i到顶点n-1的最短路径上的下一顶点

 void duoduantu(int cost[100],intc[100][100],int path[100],int k,int n){

  int i,j;

  for(i=0; i<n; i++)

    cost[i]=c[i][n-1]; //初始,c[][]记录各顶点间的距离  

  for(i=n-2; i>=k; i--)

  for(j=i+1; j<n; j++)

  if( (cost[j] + c[i][j]) <cost[i]){

  cost[i]= cost[j] + c[i][j] ;

  path[i]=j;

  }

 }

 int main(){

    int i,j,n;

    int c[100][100],cost[100], path[100];

   cout<<"输入城市个数:";

   cin>>n;

   cout<<"输入城市之间的距离:";

    for(i=0;i<n; i++)

    for(j=0;j<n; j++)

   cin>>c[i][j];

    

  duoduantu(cost,c,path,0,n);

 cout<<"最短路径长为:"<<cost[0]<<endl;

 

  for(i=0; i<=n-2; i++)

  duoduantu(cost,c,path,i,n);

 cout<<"最短路径为:"<<0<<"->";

        i=0;

  do{

 cout<<path[i];

  if(i!=n-2)cout<<"->";

  i=path[i];

  }while(i<n-2);

 cout<<n-1<<endl;

    return 0;

 }

 =========================================