演算法分析 遞迴與分治
阿新 • • 發佈:2018-11-04
1. Fibonacci數列
無窮數列1,1,2,3,5,8,13,21,34,55,……,稱為Fibonacci數列。它可以遞迴地定義為:
第n個Fibonacci數可遞迴地計算如下:
int fibonacci(int n)
{
if (n <= 1) return 1;
return fibonacci(n-1)+fibonacci(n-2);
}
- 編寫完整的主函式,分別記錄利用上述遞迴函式求第45,46,47,48個Fibonacci數所花費的時間。
#include<stdio.h> #include<time.h> long fibonacci(int n) { if (n <= 1) return 1; return fibonacci(n-1)+fibonacci(n-2); } void main() { int N,i; double s; clock_t start , stop; for(i=45;i<=48;i++){ start=clock(); fibonacci(i); printf("第%d個執行時間",i); stop=clock(); s=(stop-start)/CLK_TCK; printf(" %lfs\n",s); } }
(2)將遞迴函式改為尾遞迴,或者是遞推函式,求第45,46,47,48個Fibonacci數所花費的時間,觀察效率是否得到提高。
#include<stdio.h> #include<time.h> long tailfib(int n,int acc1,int acc2) { if (n < 2) { return acc1; } return tailfib(n-1,acc2,acc1 + acc2); } void main() { int N,i; double s; clock_t start , stop; for(i=45;i<=48;i++){ start=clock(); printf("%d:%lld",i,tailfib(i,1,1)); stop=clock(); s=(stop-start)/CLK_TCK; printf(" %lfs\n",s); } }
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int a[100];
int n;
int max; //當前最大元素
int f(int n)
{
int min; //當前最小元素
if(n==2) //只有兩個元素時,直接求解(最小問題)
{
if(a[n-2]>a[n-1]){
max=a[n-2],min=a[n-1];
}
else{
max=a[n-1],min=a[n-2];
}
return min;
}
else
{
min=f(n-1); //遞迴找第二大元素
if(a[n-1]>max){
min=max,max=a[n-1]; //找到前面n-1個元素中最大和第二大元素時
}
if(a[n-1]<max&&a[n-1]>min){
min=a[n-1]; //再與第n個元素比較找第二大元素
}
return min; //返回結果
}
}
void random()
{
srand(time(NULL));
for(int i=0;i<n;i++)
{
a[i]=1+rand()%100;
}
}
int main()
{
int s;
printf("請輸入元素的個數n:");
scanf("%d",&n);
random();
printf("\n這n個數依次為: ");
for(int j=0;j<n;j++)
printf("%d\t",a[j]);
s=f(n);
printf("\n\n這n個數中第二大元素為:%d\n",s);
return 0;
}
5. 棋盤覆蓋問題
在一個2k×2k 個方格組成的棋盤中,恰有一個方格與其它方格不同,稱該方格為一特殊方格,且稱該棋盤為一特殊棋盤。在棋盤覆蓋問題中,要用圖示的4種不同形態的L型骨牌覆蓋給定的特殊棋盤上除特殊方格以外的所有方格,且任何2個L型骨牌不得重疊覆蓋。
演算法描述如下:
引數說明:
子棋盤:由棋盤左上角的座標tr,tc和棋盤大小size表示。
特殊方格:在二維陣列中的座標位置是(dr,dc)。
#include<stdio.h>
int Martrix[100][100];
int tile=0; //整形變數,記錄L型骨牌的數量
void chessBoard(int tr, int tc, int dr, int dc, int size) //tr和tc分別是棋盤左上角方格的行號,列號; dr和dc分別代表特殊方格的行號,列號
{
int s,t;
if (1 == size) return;
s = size/2; //分割棋盤
t = ++ tile; //L型骨牌號,初始值為0
if (dr < tr + s && dc < tc +s) //用L型骨牌號覆蓋左上角子棋盤
{
chessBoard(tr,tc,dr,dc,s);//特殊方格在此棋盤中
}
else //特殊方格不在此棋盤中用,t號L型骨牌覆蓋右下角
{
Martrix[tr+s-1][tc+s-1] = t; //覆蓋本子棋盤中的其餘方格
chessBoard(tr,tc,tr+s-1,tc+s-1,s);
}
if (dr < tr + s && dc >= tc + s ) //用L型骨牌號覆蓋右上角子棋盤
{
chessBoard(tr,tc+s,dr,dc,s); //特殊方格在此棋盤中
}
else //特殊方格不在此棋盤中用,t號L型骨牌覆蓋左下角
{
Martrix[tr+s-1][tc+s] = t; //覆蓋本子棋盤中的其餘方格
chessBoard(tr,tc+s,tr+s-1,tc+s,s);
}
if (dr >= tr + s && dc < tc + s) //用L型骨牌號覆蓋右上角棋盤
{
chessBoard(tr+s,tc,dr,dc,s); //特殊方格在此棋盤中
}
else //特殊方格不在此棋盤中,用t號L型骨牌覆蓋左下角
{
Martrix[tr+s][tc+s-1] = t; //覆蓋本子棋盤中的其餘方格
chessBoard(tr+s,tc,tr+s,tc+s-1,s);
}
if (dr >= tr + s && dc >= tc + s) //用L型骨牌號覆蓋右上角子棋盤
{
chessBoard(tr+s,tc+s,dr,dc,s); //特殊方格在此棋盤中
}
else //特殊方格不在此棋盤中用t號L型骨牌左上角
{
Martrix[tr+s][tc+s] = t; //覆蓋本子棋盤中的其餘方格
chessBoard(tr+s,tc+s,tr+s,tc+s,s);
}
}
int main()
{
int size,r,c,row,col;
printf("設定棋盤大小:");
scanf("%d",&size);
printf("\n輸入特殊方格位置:(x,y) ");
scanf("%d%d",&row,&col);
chessBoard(0,0,row,col,size);
for (r = 0; r < size; r++)
{
for (c = 0;c<size; c++)
{
printf("%2d ",Martrix[r][c]);
}
printf("\n");
}
return 0;
}