问题1:集合划分
算法思想:对于n个元素的集合,可以划分为由m个子集构成的集合,例如{{1,2}{3,4}}就是由2个子集构成的非空子集。假设f(n,m)表示将n个元素划分成由m个子集构成的集合的个数。那么1)若m == 1 , 则f(n,m)= 1 ;
2)若n == m ,则f(n,m)= 1 ;3)若不是上面两种情况则有下面两种情况构成:3.1)向n-1个元素划分成的m个集合里面添加一个新的元素,则有m*f(n-1,m)种方法;3.2)向n-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– ; //从右向左扫描,找到第一个小于temp的a[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– ; //从右向左扫描,找到第一个小于temp的a[j]
if( i < j ) //表示找到a[j],则a[i],a[j]交换
{
a[i] = a[j] ;
i++ ;
}
while( i < j && a[i] < temp )
i++ ; //从左向右扫描,找到第一个大于temp的a[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 ;
}