Java语言实现五种常用的算法的应用举例

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Alex_yuan666/article/details/51568701


    用动态规划法解决最大子段和问题

二、实验目的: 

      课程设计是《算法分析与设计》课程不可缺少的重要实践性环节。通过实践教学,要达到以下目的:

(1)使学生掌握动态规划法思想

(2)使学生掌握以抽象数据类型为模块的面向对象程序设计方法;

(3)使学生提高对实际问题的分析、设计和实现能力;

(4)为学生后续课程的学习及课程设计打下坚实的实践基础。

 三、使用的策略:

 动态规划法思想

四、实验内容:

(一) 问题描述

给定由n个整数(可能为负整数)组成的序列a1,a2,a3,···,an,求该序列的子段和的最大值。当所有整数均为负整数是定义其最大子段和为0,一次定义,所求的最优质值为:max{0、max子段和}。

(二) 算法描述

动态规划法的基本思想:

动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值的解。

算法设计:

#include "stdafx.h"

int MaxSum(int a[],int n,int &Start,int&End){

       intsum=0;

       int*b,t;

       b=newint[n+1];

       b[0]=0;

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

              if(b[i-1]>0){

                     b[i]=b[i-1]+a[i];

              }

              else {

                     b[i]=a[i];t=i;

              }

              if(b[i]>sum){

                     sum=b[i];

                     Start=t;

                     End=i;

              }

       }

       delete[]b;

       returnsum;

}

int main(int argc, char* argv[])

{

       inta[7]={0,-2,11,-4,13,-5,-2},sum,Start,End,i;

       sum=MaxSum(a,6,Start,End);

       for(i=Start;i<=End;i++){

              printf("%d ",a[i]);

       }

       printf("\n%d\n",sum);

       getchar();

       getchar();

       return0;

}

    用分支界限法解决最大子段和问题

二、实验目的: 

      课程设计是《算法分析与设计》课程不可缺少的重要实践性环节。通过实践教学,要达到以下目的:

(1)使学生掌握分支界限法思想

(2)使学生掌握以抽象数据类型为模块的面向对象程序设计方法;

(3)使学生提高对实际问题的分析、设计和实现能力;

(4)为学生后续课程的学习及课程设计打下坚实的实践基础。

 三、使用的策略:

     分支界限法

四、实验内容:

(一) 问题描述

在下图所给的有向图G中,每一边都有一个非负边权。要求图G的从源顶点s到目标顶点t之间的最短路径。

(二) 算法描述

分支界限法的基本思想:

分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树。

在分支限界法中,每一个活结点只有一次机会成为扩展结点。活结点一旦成为扩展结点,就一次性产生其所有儿子结点。在这些儿子结点中,导致不可行解或导致非最优解的儿子结点被舍弃,其余儿子结点被加入活结点表中。

 此后,从活结点表中取下一结点成为当前扩展结点,并重复上述结点扩展过程。这个过程一直持续到找到所需的解或活结点表为空时为止。

算法设计:

#include<iostream>

#include<vector>

#include<queue>

#include<limits>

using namespacestd;

struct node_info

{

public:

    node_info (int i,int w)

        : index (i), weight (w) {}

    node_info ()

        : index(0),weight(0) {}

    node_info (const node_info & ni)

        : index (ni.index), weight (ni.weight){}

    friend

    bool operator < (const node_info&lth,const node_info& rth) {

        return lth.weight > rth.weight ; // 为了实现从小到大的顺序

    }

public:

    int index; // 结点位置

    int weight; // 权值

};

struct path_info

{

public:

    path_info ()

        : front_index(0), weight(numeric_limits<int>::max()) {}

public:

    int front_index;

    int weight;

};

// single sourceshortest paths

classss_shortest_paths

{

    

public:

    ss_shortest_paths (constvector<vector<int> >& g,int end_location)

        :no_edge (-1), end_node (end_location),node_count (g.size()) , graph (g)

    {}

    // 打印最短路径

    void print_spaths () const {

        cout << "min weight : "<< shortest_path << endl;

        cout << "path: " ;

        copy(s_path_index.rbegin(),s_path_index.rend(),

            ostream_iterator<int> (cout," "));

        cout << endl;

    }

    // 求最短路径

    void shortest_paths () {

        vector<path_info>path(node_count);

       priority_queue<node_info,vector<node_info> > min_heap;

        min_heap.push (node_info(0,0));    // 将起始结点入队

        while (true) {

            node_info top = min_heap.top();    // 取出最大值

            min_heap.pop ();

            // 已到达目的结点

            if (top.index == end_node) {

                break ;

            }

            // 未到达则遍历

            for (int i = 0; i < node_count;++ i) {

                // 顶点top.index和i间有边,且此路径长小于原先从原点到i的路径长

                if (graph[top.index][i] !=no_edge &&

                    (top.weight +graph[top.index][i]) < path[i].weight) {

                    min_heap.push (node_info(i,top.weight + graph[top.index][i]));

                    path[i].front_index =top.index;

                    path[i].weight = top.weight+ graph[top.index][i];

                }

            }

            if (min_heap.empty()) {

                break ;

            }

        }

        shortest_path = path[end_node].weight;

        int index = end_node;

        s_path_index.push_back(index) ;

        while (true) {

            index = path[index].front_index ;

            s_path_index.push_back(index);

            if (index == 0) {

                break;

            }

        }

    }

private:

    vector<vector<int> >    graph ;            // 图的数组表示

    int                        node_count;        // 结点个数

    const int                no_edge;        // 无通路

    const int                end_node;        // 目的结点

    vector<int>                s_path_index;    // 最短路径

    int                        shortest_path;    // 最短路径

};

int main()

{

    const int size = 11;

    vector<vector<int> > graph(size);

    for (int i = 0;i < size; ++ i) {

        graph[i].resize (size);

    }

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

        for (int j = 0;j < size; ++ j) {

            graph[i][j] = -1;

        }

    }

    graph[0][1] = 2;

    graph[0][2] = 3;

    graph[0][3] = 4;

    graph[1][2] = 3;

    graph[1][5] = 2;

    graph[1][4] = 7;

    graph[2][5] = 9;

    graph[2][6] = 2;

    graph[3][6] = 2;

    graph[4][7] = 3;

    graph[4][8] = 3;

    graph[5][6] = 1;

    graph[5][8] = 3;

    graph[6][9] = 1;

    graph[6][8] = 5;

    graph[7][10] = 3;

    graph[8][10] = 2;

    graph[9][8] = 2;

    graph[9][10] = 2;

    ss_shortest_paths ssp (graph, 10);

    ssp.shortest_paths ();

    ssp.print_spaths ();

       getchar();

    return 0;

}


   

    用分治法解决最大子段和问题

二、实验目的: 

      课程设计是《算法分析与设计》课程不可缺少的重要实践性环节。通过实践教学,要达到以下目的:

(1)使学生掌握分治法思想

(2)使学生掌握以抽象数据类型为模块的面向对象程序设计方法;

(3)使学生提高对实际问题的分析、设计和实现能力;

(4)为学生后续课程的学习及课程设计打下坚实的实践基础。

 三、使用的策略:

     分治法算法

四、实验内容:

(一) 问题描述

给定由n个整数(可能为负整数)组成的序列a1,a2,a3,···,an,求该序列的子段和的最大值。当所有整数均为负整数是定义其最大子段和为0,一次定义,所求的最优质值为:max{0、max子段和}。

(二) 算法描述

分治算法的基本思想:

分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同。求出子问题的解,就可得到原问题的解。即一种分目标完成程序算法,简单问题可用二分法完成

算法设计:

#include "stdafx.h"

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

       intsum=0,center,LeftSum,RightSum;

       ints1,lefts,s2,rights,i;

       if(left==right)

          sum=a[left]>0?a[left]:0;

       else{

         center=(left+right)/2;

       //求出第(1)种情况的最大字段和

         LeftSum=MAXSubsum(a,left,center);

       //求出第(2)种情况的最大字段和

         RightSum=MAXSubsum(a,center+1,right);

       //求出第(3)种情况的最大字段和

       s1=0,lefts=0;

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

              lefts+=a[i];

              if(lefts>s1)s1=lefts;

       }

       //第三种情况左边的和

         s2=0,rights=0;

       for(i=center+1;i<=right;i++)

       {

               rights+=a[i];

               if(rights>s2)s2=rights;

       }

       //右边的和

        sum=s1+s2;//保存了第三种情况字段和

        if(sum<LeftSum)sum=LeftSum;

        if(sum<RightSum)sum=RightSum;

       }

       returnsum;

}

int main(int argc, char* argv[])

{

       inta[7]={0,-2,11,-4,13,-5,-2},sum;

       sum=MAXSubsum(a,1,6);

       printf("%d\n",sum);

       getchar();

       getchar();

       return0;

}

用回溯题算法解决背包问题

二、实验目的: 

      课程设计是《算法分析与设计》课程不可缺少的重要实践性环节。通过实践教学,要达到以下目的:

(1)使学生掌握回溯法的定义

(2)使学生掌握以抽象数据类型为模块的面向对象程序设计方法;

(3)使学生提高对实际问题的分析、设计和实现能力;

(4)为学生后续课程的学习及课程设计打下坚实的实践基础。

 三、使用的策略:

      回溯算法                      

四、实验内容:

(一) 问题描述

给定一个最大重量为M的背包和N种物品,已知第i种物品是Wi公斤,其价值为Vi元,编程确定一个装货方案,是的装入背包中的所有物品总价值最大。

(二) 算法描述

回溯算法解决方案:

回溯算法的基本思想

回溯法(探索与回溯法)是一种选优搜索法,又称为试探法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法,而满足回溯条件的某个状态的点称为回溯点

设计算法:

#include "stdafx.h" 

#include <iostream>  

using namespace std;  

 

using namespace std;

#define max(a,b)((a)>(b)?(a):(b))

 

int bestValue=0;

 

void backSearch(int *weight,int *value,int capacity,int num,int *mark,intstep,int tempValue,int tempWeight)

{

 int i;

 

 if (step>num)

 {

  if (tempValue>bestValue)

  {

   bestValue=tempValue;

  cout<<bestValue<<endl;

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

   {

   cout<<mark[i]<<" ";

   }

   cout<<endl;

  }

  return ;

 }

 else

 {

  if(tempWeight+weight[step]<=capacity)

  {

   mark[step]=1;

  backSearch(weight,value,capacity,num,mark,step+1,tempValue+value[step],tempWeight+weight[step]);

  }

  mark[step]=0;//注意

 backSearch(weight,value,capacity,num,mark,step+1,tempValue,tempWeight);

 }

}

 

int main()

{

    int capacity,num;

    int *weight,*value,*mark;

    int i;

  

    printf("请输入包的容量:");

   scanf("%d",&capacity);

    printf("请输入物品的数量:");

    scanf("%d",&num);

      

    weight=(int*)malloc(sizeof(int)*(num+1));

    value=(int*)malloc(sizeof(int)*(num+1));

 mark=(int*)malloc(sizeof(int)*(num+1));

 

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

    {

  printf("请输入第%d件物品的重量:",i);

 scanf("%d",weight+i); 

  printf("请输入第%d件物品的价值:",i);

  scanf("%d",value+i);

 

  printf("\n");          

    }

 

 backSearch(weight,value,capacity,num,mark,1,0,0);

    printf("书包可容纳的最大价值为:%d\n",bestValue);

 

    free(weight);

    free(value);

 free(mark);

 

    system("pause");

    return 0; 

}

用贪心算法解决背包问题   

二、实验目的: 

      课程设计是《算法分析与设计》课程不可缺少的重要实践性环节。通过实践教学,要达到以下目的:

(1)使学生掌握贪心算法的定义

(2)使学生掌握以抽象数据类型为模块的面向对象程序设计方法;

(3)使学生提高对实际问题的分析、设计和实现能力;

(4)为学生后续课程的学习及课程设计打下坚实的实践基础。

 三、使用的策略:

     贪心算法

四、实验内容:

(一) 问题描述

给定一个最大重量为M的背包和N种物品,已知第i种物品是Wi公斤,其价值为Vi元,编程确定一个装货方案,是的装入背包中的所有物品总价值最大。

(二) 算法描述

贪心算法解决方案:

贪心算法的基本思想

贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解

算法设计:

#include "stdafx.h" 

#include <iostream>  

using namespace std;  

 

const int N = 3; 

 

void Gr(int n,float M,float v[],floatw[],float x[]); 

 

int main() 

   float M = 50;//背包所能容纳的重量  

  float w[] = {10,20,30};

   float v[] = {100,250,300}; 

 

   float x[N+1]; 

 

   cout<<"背包所能容纳的重量为:"<<M<<endl; 

   cout<<"待装物品的重量和价值分别为:"<<endl; 

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

   { 

       cout<<"["<<i<<"]:("<<w[i]<<","<<v[i]<<")"<<endl; 

   } 

     

   Gr(N,M,v,w,x); 

 

  cout<<"选择装下的物品比例如下:"<<endl; 

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

   { 

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

   } 

 getchar();

  return 0; 

 

void Gr(int n,float M,float v[],floatw[],float x[]) 

  

   int i; 

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

   { 

       x[i]=0;//初始化数组x[] 

  } 

 

  float c=M; 

  for (i=1;i<=n;i++)//物品整件被装下,x[i]=1 

  { 

       if (w[i]>c) 

      { 

            break; 

       } 

      x[i]=1; 

      c-=w[i]; 

 

  //物品i只有部分被装下 

  if (i<=n) 

  { 

      x[i]=c/w[i]; 

  } 

 


猜你喜欢

转载自blog.csdn.net/Alex_yuan666/article/details/51568701