递归与分治算法实验报告

问题1:集合划分

算法思想:对于n个元素的集合,可以划分为由m个子集构成的集合,例如{{1,2}{3,4}}就是由2个子集构成的非空子集。假设fnm)表示将n个元素划分成由m个子集构成的集合的个数。那么1)若m == 1 , 则fnm= 1 

2)若n == m ,则fnm= 1 3)若不是上面两种情况则有下面两种情况构成:3.1n-1个元素划分成的m个集合里面添加一个新的元素,则有m*f(n-1,m)种方法;3.2n-1个元素划分成的m-1个集合里添加一个由一个元素形成的独立的集合,则有f(n-1,m-1)种方法。

实验代码:

#include<iostream>

#include<fstream>

using namespace std ;

int jihehuafen( int n , int m )

{

if( m == 1 || n == m )

return 1 ;

else

return jihehuafen( n – 1 , m – 1 ) + m*jihehuafen( n – 1 , m ) ;

}

int main()

{

ifstream fin(“C:/input.txt”) ;

ofstream fout(“C:/output.txt”) ;

int N , M , num ;

fin >> N >> M ;

    num = jihehuafen( N , M) ;

fout << num << endl ;

return 0 ;

}

问题2:输油管道

算法思想:由于主管道由东向西铺设。故主管道的铺设位置只和各油井的y坐标有关。要使主管道的y坐标最小,主管道的位置y坐标应是各个油井y坐标的中位数。先用快速排序法把各个油井的y坐标排序,然后取其中位数再计算各个油井y坐标与中位数差值的绝对值之和。

实验代码:

#include<iostream>

#include<fstream>

#include<cmath>

using namespace std ;

struct point//定义坐标结构体

{

int x ;

int y ;

};

//快速排序

void sort( point a[] , int size )

{

int i = 0 , j = size – 1 ;

int temp ;//用来保存作为基准的数

if( size >= 1 )

{

temp = a[0].y ;//用区间的第一个元素作为基准

while( i != j )//区间两端交替向中间扫描,知道i = j

{

while( i < j && a[j].y > temp )

j– ; //从右向左扫描,找到第一个小于tempa[j]

if( i < j )//表示找到a[j] ,把a[j] 赋给a[i]

{

a[i].y = a[j].y ;

i++ ;

}

while( i < j && a[i].y < temp )

i++ ;//从左向右扫描,找到第一个大于temp a[i]

if( i < j )//表示找到a[i],把a[i]赋给a[j]

{

a[j].y = a[i].y ;

j– ;

}

}

a[i].y = temp ;

sort( a , i ) ;//对左递归

sort( a + i + 1 , size – i – 1 ) ;//对右递归

}

}

//取中位数

int madian( point *a , int size )

{

int num =  size + 1 ;

return a[num/2 – 1].y ;

//return  size%2 ? a[size>>1].y :( a[size>>1].y + a[ (size>>1) +1 ].y)>>1 ;

}

//计算最短路程

int lucheng( point *a , int size )

{

int mid = madian( a , size ) ; 

int i , sum = 0 ; 

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

{

sum +=abs( a[i].y – mid ) ; 

}

return sum ;

}

int main()

{

ifstream fin( “C:/input.txt”) ;

ofstream fout( “C:/output.txt”) ;

int n ; 

fin >> n ;

    point *p = new point[n] ;

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

fin >> p[i].x >> p[i].y ;

    sort( p ,  n ) ;

int minlen = lucheng( p , n) ;

fout << minlen << endl ;

return 0 ;

}

问题3:邮局选址问题

算法思想:同问题2

实验代码:

#include<iostream>

#include<fstream>

#include<cmath>

using namespace std ;

struct point

{

int x ;

int y ;

} ;

void sort_x( point *a , int size )

{

int temp ;

int i = 0 , j = size – 1 ;

if( size >= 1 )

{

temp = a[0].x ;//

while( i != j )

{

while( i < j && a[j].x > temp )

j– ;

if( i < j )

{

a[i].x = a[j].x ;

i++ ;

}

while( i < j && a[i].x < temp )

i++ ;

if( i < j )

{

a[j].x = a[i].x ;

j– ;

}

}

a[i].x = temp;

sort_x( a , i ) ;//

sort_x( a + i +1 , size – i – 1 ) ;//

}

}

void sort_y( point *a , int size )

{

int temp ;

int i = 0 , j = size – 1 ;

if( size >= 1 )

{

temp = a[0].y ;//

while( i < j )

{

while( i < j && a[j].y > temp )

j– ;

if( i < j )

{

a[i].y = a[j].y ;

i++ ;

}

while( i < j && a[i].y < temp )

i++ ;

if( i < j )

{

a[j].y = a[i].y ;

j– ;

}

}

a[i].y = temp;

sort_y( a , i ) ;//

sort_y( a + i +1 , size – i – 1 ) ;//

}

}

int madian_x( point *a , int size )

{

//int num =  size + 1 ;

//return a[num/2 – 1].x ;

return  size%2 ? a[size>>1].x :( a[size>>1].x + a[ (size>>1) +1 ].x)>>1 ;

}

int madian_y( point *a , int size )

{

int num =  size + 1 ;

return a[num/2 – 1].y ;

//return  size%2 ? a[size>>1].y :( a[size>>1].y + a[ (size>>1) +1 ].y)>>1 ;

}

int lucheng( point *a , int size )

{

int mid_x = madian_x( a , size ) ;

int mid_y = madian_y( a , size ) ;

int i , sum = 0 ; 

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

{

sum += abs( a[i].y – mid_y )  + abs(a[i].x – mid_x ) ; 

}

return sum ;

}

int main()

{

ifstream fin(“C:/input.txt”) ;

ofstream fout(“C:/output.txt”) ;

if( !fin )

{

cout<<“the file can’t open!”<<endl;

return – 1 ;

}

int n ;

fin >> n ;

point *p = new point[n] ;

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

{

fin >> p[i].x >> p[i].y ;

}

    sort_x( p , n ) ;

sort_y( p , n ) ;

int minlen = lucheng( p , n ) ;

fout << minlen << endl ;

delete []p ;

return 0 ;

}

问题4:整数因子分解问题

算法思想:采用递归的算法思想

实验代码:

#include<iostream>

#include<fstream>

using namespace std ;

int count = 0 ;

void yinzifenjie( int x )

{

if( x == 1 )

{

count++;

    }

    else

    {

for( int i = 2 ; i <= x ; i++ )

{

if( x % i == 0 )

{

yinzifenjie(x/i);

            }

        }

        

    }

}

int main()

{

ifstream fin(“C:/input.txt”) ;

ofstream fout(“C:/output.txt”) ;

if( !fin )

 {

 cout<<“the file can’t open!”<<endl;

 return – 1 ;

 }

int x ;

fin >> x ;

yinzifenjie(x) ;

fout << count << endl ;

return 0 ;

}

问题5:众数问题

算法思想:首先利用快速排序将其数组排序,利用写的求中位数函数及其返回中位数起始点函数编写求众数。求众数函数思想是:找到中位数及其起始结束点,将众数初始化为中位数。判断起点左边的元素数是否大于中位数的重数,如果大于则向左递归找众数,再判断终点右边的元素数是否大于中位数的重数,如果大于则向右递归找众数。

实验代码:

#include<iostream>

#include<fstream>

using namespace std ;

//结构体用来保存众数的元素与重数

typedef struct

{

int element;  //元素

    int sum;  //重数

}zhongshu;

//记录中位数的起始下标

typedef struct

{

int low;

int high;

}node;

//快排

zhongshu x ;

void sort( int a[] , int s , int t )//a[s]a[t]的元素排序 

{

int i = s , j = t ;

int temp ;

if( s < t ) //区间里至少存在一个元素的情况

{

temp = a[s] ; //用区间的第一个元素做基准

while( i != j ) //区间两端交替向中间扫描,直到I=J

while( j > i && a[j] > temp )

j– ; //从右向左扫描,找到第一个小于tempa[j]

if( i < j ) //表示找到a[j],a[i],a[j]交换

{

a[i] = a[j] ;

                i++ ;

}

while( i < j && a[i] < temp )

i++ ; //从左向右扫描,找到第一个大于tempa[i]

if( i < j ) //表示找到a[i],a[i],a[j]交换

{

a[j] = a[i] ;

                j– ;

}

}

a[i] = temp ;

sort( a , s , i – 1 ) ; //对左递归

        sort( a , i + 1 , t ) ; //对右递归

}

 }

 //中位数

int madian( int *a , int L , int R )

{

int num = L + R + 1 ;

return a[num/2] ;

}

 //返回中位数的起始点终点

node spalit(int *a , int med , int L , int R )

{

 node m ;

     m.low = L ; 

 m.high = R ;

     for( int i = 0 ; i <= R ; i++ )

 {

 if( med == a[i] )

 {

 m.low = i ;

 break ;

 }

 }

     for( int j = R ; j >= 0 ; j– )

 {

 if( med == a[j] )

 {

 m.high = j ;

 break ;

 }

 }

     return m ;

}

 //众数的重数求取

void mode( int *a , int L , int R )

{

if( L >= R ) 

return;//x.sum=0;

    else

{

node n;

        int temp = 0 ;

        int med ;

        med = madian( a , L , R ) ;

        n = spalit( a , med , L , R );

        temp = n.high – n.low + 1 ;

        if( x.sum < temp )

{

x.element = med ;

            x.sum = temp ;

}

if( n.low – L > temp )//

{

if( x.sum < temp )

{

x.element = med ;

                x.sum = temp ;

}

mode(a , L , n.low – 1 ) ;

}

if( R – n.high > temp )

{

if( x.sum < temp )

{

x.element = med ;

x.sum=temp;

}

mode( a , n.high + 1 , R ) ;

}

  }

 }

 int main()

 {

 x.sum = 0 ;

     int n ;

     int *a ;

     ifstream fin(“C:/input.txt”);

 ofstream fout(“C:/output.tex”);

     if( !fin )

 {

 cout<<“the file can’t open!”<<endl;

 return – 1 ;

 }

     fin >> n ;

     a = new int[n];

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

 {

 fin >> a[i] ;

     }

     sort(a,0,n-1);

     mode(a,0,n-1);

     fout << x.element << endl << x.sum;

     delete []a;

 return 0 ;

}

 

    原文作者:递归与分治算法
    原文地址: https://blog.csdn.net/u010158265/article/details/8782701
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞