算 法 設 計 題 集
第一章 算法初步
第一節 程序設計與算法
暱稱:狂飛
QQ:18670340
注意事項:本文均爲作者個人編寫如果紕漏
請給予指出,轉載請標明出處
一、算法
算法是解決問題方法的精確描述,但是並不是所有問題都有算法,有些問題經研究可行,則相應有算法,但這並不是說問題就有結果。上述的“可行”,是指對算法的研究。
1.待解問題的描述
待解問題表述應精確、簡練、清楚,使用形式化模型刻劃問題是最恰當的。例如,使用數學模型刻劃問題是最簡明、嚴格的,一旦問題形式化了,就可依據相應嚴格的模型對問題求解。
2.算法設計
算法設計的任務是對各類具體問題設計良好的算法及研究設計算法的規律和方法。常用的算法有:窮舉搜索法、遞歸法、回溯法、貪心法、分治法等。
3.算法分析
算法分析的任務是對設計出的每一個具體的算法,利用數學工具,討論各種複雜度,以探討某種具體算法適用於哪類問題,或某類問題宜採用哪種算法。
算法的複雜度分時間複雜度和空間複雜度。
.時間複雜度:在運行算法時所耗費的時間爲f(n)(即 n的函數)。
.空間複雜度:實現算法所佔用的空間爲g(n)(也爲n的函數)。
稱O(f(n))和O(g(n))爲該算法的複雜度。
二、程序設計
1.程序
程序是對所要解決的問題的各個對象和處理規則的描述,或者說是數據結構和算法的描述,因此有人說,數據結構+算法=程序。
2.程序設計
程序設計就是設計、編制和調試程序的過程。
3.結構化程序設計
結構化程序設計是利用逐步求精的方法,按一套程式化的設計準則進行程序的設計。由這種方法產生的程序是結構良好的。所謂“結構良好”是指:
(1)易於保證和驗證其正確性;
(2)易於閱讀、易於理解和易於維護。
按照這種方法或準則設計出來的程序稱爲結構化的程序。
“逐步求精”是對一個複雜問題,不是一步就編成一個可執行的程序,而是分步進行。
.第一步編出的程序最爲抽象;
.第二步編出的程序是把第一步所編的程序(如過程、函數等)細化,較爲抽象;
.……
.第i步編出的程序比第i-1步抽象級要低;
.……
.直到最後,第n步編出的程序即爲可執行的程序。
所謂“抽象程序”是指程序所描述的解決問題的處理規則,是由那些“做什麼”操作組成,而不涉及這些操作“怎樣做”以及解決問題的對象具有什麼結構,不涉及構造的每個局部細節。
這一方法原理就是:對一個問題(或任務),程序人員應立足於全局,考慮如何解決這一問題的總體關係,而不涉及每局部細節。在確保全局的正確性之後,再分別對每一局部進行考慮,每個局部又將是一個問題或任務,因而這一方法是自頂而下的,同時也是逐步求精的。採用逐步求精的優點是:
(1)便於構造程序。由這種方法產生的程序,其結構清晰、易讀、易寫、易理解、易調試、易維護;
(2)適用於大任務、多人員設計,也便於軟件管理。
逐步求精方法有多種具體做法,例如流程圖方法、基於過程或函數的方法。
[例]求兩自然數,其和是667,最小公倍數與最大公約數之比是120:1(例如(115,552) 、(232,435))。
[解]兩個自然數分別爲m和667-m(2≤m≤ 333)。
處理對象:m(自然數)、l(兩數的最小公倍數)、g(兩數的最大公約數)。
處理步驟:對m從2到333檢查l與g的商爲120,且餘數爲0時,打印m與667-m 。
第一層抽象程序:
Program TwoNum;
Var m,l,g:integer;
Begin for m:=2 to 333 do
begin l:=lcm(m,667-m); {求最小公倍數}
g:=gcd(m,667-m); {求最大公約數}
if (l=g*120)and(l mod g=0) then
writeln(m:5,667-m:5);
end;
End.
第二層考慮函數lcm(最小公倍數)、gcd(最大公約數)的細化。
最大公約數問題是對參數a、b,找到一個數i能整除a與b,i就是gcd的函數值。
Function gcd(a,b:integer):integer;
var i:integer;
begin for i:=a downto 1 do
if not((a mod i=0)or(b mod i=0)) then gcd:=i;
end;
而最小公倍數的計算是:若干個b之和,若能被a整除,則該和便是a、b的最小公倍數。
Function lcm(a,b:integer):integer;
var i:integer;
begin i:=b;
while i mod a=0 do i:=i+b;
lcm:=i;
end;
第二節 編程入門題例
編程入門題(一)
1、位數對調:輸入一個三位自然數,把這個數的百位與個位數對調,輸出對
調後的數。例如:Input 3 bit natrue data:234
n=432
[解]1.先確定輸入數n是否三位數,即n>99且n<=999。
2.位數對調:n=abc→cba=x
①百位數a=n整除100;②十位數b=(n-a*100)整除10;③個位數c=n除以10的餘數;
3.得對調後的數:x=c*100+b*10+a
[程序]
{$I-} {輸入的數據爲整數}
program Threebit;
var x,n,a,b,c:INTEGER;
BEGIN write('Input 3 bit nature data:'); readln(n);
IF (n>99) and (n<1000) then
begin a:=n DIV 100; {求百位數}
b:=(n-a*100) DIV 10;{求十位數}
c:=n mod 10; {求個位數}
x:=c*100+b*10+a; {得新數X}
writeln('Number=',x:3);
end
ELSE writeln('Input error!');
END.
2、求三角形面積:給出三角形的三個邊長爲a,b,c,求三角形的面積。
提示:根據海倫公式來計算三角形的面積:
S= ;Area=
[解]1.輸入的三角形三邊長a,b,c要滿足“任意兩邊長的和大於第三邊長”。
2.按海倫公式計算:s=(a+b+c)/2;x=s*(s-a)*(s-b)*(s-c)
這時若x>=0,則求面積:area= ,並輸出area的值。
[程序]
PROGRAM hl;
VAR a,b,c,s,x,area:real;
BEGIN
write('Input a,b,c:');readln(a,b,c);
If (a>0) and (b>0) and (c>0) and (a+b>c)and(a+c>b)and(b+c>a) Then
Begin s:=(a+b+c)/2; x:=s*(s-a)*(s-b)*(s-c);
If x>=0 Then Begin Area:=SQRT(x);writeln('Area=',area:8:5); End;
End
Else writeln('Input error!')
END.
3、模擬計算器:試編寫一個根據用戶鍵入的兩個操作數和一個運算符,由計算機輸出運算結果的程序。這裏只考慮加(+)、減(-)、乘(*)、除(/)四種運算。
例1:Input x,y:15 3
Input operator(+,-,*,/):+
15.00+ 3.00= 18.00
例2:Input x,y:5 0
Input operator(+,-,*,/):/
divide is zero!
[解]該題關鍵是判斷輸入的兩數是作何種運算(由輸入的運算符operator決定, 如'+'、'-'、'*'、'/'分別表示加、減、乘、除法的運算)。其中要進行除(/)運算時,要先進行合法性檢查,即除數不能爲0。
[程序]
PROGRAM Oper;
Var x,y,n:real;
operator:char;
Begin
write('Input x,y:');readln(x,y);
write('Input operator:');readln(operator);
Case operator of
'+':n:=x+y; {加法運算}
'-':n:=x-y; {減法運算}
'*':n:=x*y; {乘法運算}
'/':If y=0 then {除法運算}
begin writeln('Divide is zero!');halt;end
Else n:=x/y;
else begin writeln('Input operator error!');halt;end;
End;
writeln(x:6:2,operator,y:6:2,'=',n:6:2);
End.
4、念數字:編一個“念數字”的程序,它能讓計算機完成以下工作:當你輸入一個0至99之間的數後,計算機就會用漢字拼音印出這個數的念結束。
例1:Input data:35
SAN SHI WU
例2:Input data:0
LING
如果輸入的數不在0到99之間,就印出“CUO LE”(錯了),請求重新輸入。
注:爲了使不熟悉漢語拼音的同學也能做這個題,把“零,一,二,三,……,九,十”的拼音法寫在下面。
零 LING 一 YI 二 ER 三 SAN 四 SHI 五 WU
六 LIU 七 QI 八 BA 九 JIU 十 SHI
[解]輸入數在0~99之間,若x爲兩位數則拆分爲十位數、個位數。然後調用念
數過程Readdigit用漢字拼音印出各位數(0~9)的念。
[程序]
{$I-}
Program NinShu;
Var x,a,b:Integer;
Procedure ReadDigit(n:Integer);{念數過程:n=0~9}
Begin
Case n of
0:write('LING ');
1:write('YI ');
2:write('ER ');
3:write('SAN ');
4:write('SHI ');
5:write('WU ');
6:write('LIU ');
7:write('QI ');
8:write('BA ');
9:write('JIU ');
End;
End; {ReadDigit}
Begin {main}
Repeat write('Input data:');readln(x);
if (x<0) or (x>99) then writeln('Cuo Le');
Until (x>=0)and(x<=99);
If (x>=0)and(x<=9) then ReadDigit(x) {調用念數過程}
Else Begin a:=x DIV 10; b:=x mod 10; {位數拆分}
If a<>1 then ReadDigit(b);
writeln(' Shi');
if b<>0 then ReadDigit(b);
End;
writeln;
End.
5、數列找數:數組A(N)的各下標變量中N個互不相等的數,鍵盤輸入正整數M(M≤N),要求打印數組中第M大的下標變量的值。
例如:數組A(10)的數據爲:
A(1) |
A(2) |
A(3) |
A(4) |
A(5) |
A(6) |
A(7) |
A(8) |
A(9) |
A(10) |
16 |
57 |
20 |
19 |
38 |
41 |
6 |
13 |
25 |
32 |
運行結果:INPUT AN NUMBER:3
A(5)=38 (即第3大的數是A(5)=38)
[解]該題要從N個互不相等的數中找第M大的值。有以下兩種解法:
解法一:初始時:A數組存放N個互不相等的數;B數組用於存放數組A的下標。見下表一。
下標值i |
1 |
2 |
3 |
4 |