第7周練兵區編程題
NOTE:
- 尾遞歸:當遞歸調用是整個函數體中最後執行的語句且它的返回值不屬於任何表達式的一部分(即在迴歸階段不需要任何計算)時,這種遞歸調用就是尾遞歸。尾遞歸的精髓就是 通過參數傳遞結果,達到不壓棧的目的。
- 變量的作用域是指變量的作用範圍,即在程序中可以被讀寫訪問的區域,它取決於變量被定義的位置。
- 形參也是局部變量,形參變量和實參變量的作用域是不同的,因此形參變量和實參變量同名時,二者互不干擾。
- 只要同名的變量出現在不同的作用域內,二者互不干擾,編譯器有能力區分不同作用域中的同名變量。
- 變量的存儲類型決定變量的生存週期—靜態存儲區中的變量生存期是整個程序,類似於學校的宿舍;動態存儲區中的變量生存期是定義它的語句塊,類似於外面的酒店賓館。
-
extern int i; //聲明,不是定義
-
int i; //聲明,也是定義
經典遞歸算法題—漢諾塔問題
漢諾塔問題是指:一
塊板上有三根針 A、B、C。A 針上套有 64 個大小不等的圓盤,按照大的在下、小的在上的順序排列,要把這 64 個圓盤從 A 針移動到 C 針上,每次只能移動一個圓盤,移動過程可以藉助 B 針。但在任何時候,任何針上的圓盤都必須保持大盤在下,小盤在上。從鍵盤輸入需移動的圓盤個數,給出移動的過程。
算法思想:
對於漢諾塔問題,當只移動一個圓盤時,直接將圓盤從 A 針移動到 C 針。若移動的圓盤爲 n(n>1),則分成幾步走:把 (n-1) 個圓盤從 A 針移動到 B 針(藉助 C 針);A 針上的最後一個圓盤移動到 C 針;B 針上的 (n-1) 個圓盤移動到 C 針(藉助 A 針)。每做一遍,移動的圓盤少一個,逐次遞減,最後當 n 爲 1 時,完成整個移動過程。
程序代碼:
#include<stdio.h>
void move(char a,char b) //移動函數,從a移到b
{
static int k = 1;
printf("%2d: %c ---> %c\n",k,a,b);
k++;
}
void hanoit(int n,char a,char b,char c)//遞歸函數
{
if(n == 1)move(a,c);
else
{
hanoit(n - 1,a,c,b);
move(a,c);
hanoit(n - 1,b,a,c);
}
}
int main()
{
int n;
scanf("%d",&n);;
hanoit(n,'A','B','C');
return 0;
}
1. 諧均值計算
題目內容:
兩數值的諧均值可以這樣計算:首先對兩數值的倒數取平均值,最後再取倒數。編寫一個帶有兩個double參數的函數,計算這兩個參數的諧均值。
函數原型爲: double Calculate(double x,double y);
#include <stdio.h>
double Calculate(double x,double y);
int main()
{
double x,y;
printf("Input two doubles:\n");
scanf("%lf%lf",&x,&y);
printf("1/((1/x+1/y)/2) = %0.3f\n",Calculate(x,y));
return 0;
}
double Calculate(double x,double y)
{
return 1/((1/x+1/y)/2);
}
2. 輸出指定行列數的字符
題目內容:
編寫一個函數,函數原型: void Chline(char ch, int column, int row);
該函數的3個參數是一個字符和兩個整數。字符參數是需要輸出的字符。第一個整數說明了在每行中該字符輸出的個數,而第二個整數指的是需要輸出的行數。編寫一個調用該函數的程序。
#include <stdio.h>
void Chline(char ch, int column, int row);
int main()
{
char ch;
int co,row;
printf("input a char:\n");
scanf("%c",&ch);
printf("input column and row:\n");
scanf("%d%d",&co,&row);
Chline(ch,co,row);
return 0;
}
void Chline(char ch, int column, int row)
{
int i,j;
for(i = 0;i < row; i++)
{
for(j = 0;j < column; j++)
{
printf("%c",ch);
}
printf("\n");
}
}
3. 魔術師猜數
題目內容:
在一種室內互動遊戲中,魔術師要每位觀衆心裏想一個三位數abc(a、b、c分別是百位、十位和個位數字),然後魔術師讓觀衆心中記下acb、bac、bca、cab、cba五個數以及這5個數的和值。只要觀衆說出這個和是多少,則魔術師一定能猜出觀衆心裏想的原數abc是多少。例如,觀衆甲說他計算的和值是1999,則魔術師立即說出他想的數是443,而觀衆乙說他計算的和值是1998,則魔術師說:“你算錯了!”。請編程模擬這個數字魔術遊戲,要求用函數實現。
函數原型爲: int Magic(int m);
#include <stdio.h>
int Magic(int m);
int main()
{
int n;
scanf("%d",&n);
if(Magic(n) == 0)
printf("The sum you calculated is wrong!\n");
else
printf("The number is %d\n",Magic(n));
return 0;
}
int Magic(int m)
{
int a, b, c, i, sum;
for(i = 100;i <= 999; i++)
{
c = i%10;
b = (i/10)%10;
a = i/100;
sum = 122*a + 212*b + 221*c;
if(m == sum)
return i;
}
return 0;
}
4. 計算禮炮聲響次數
題目內容:
在海軍節開幕式上,有A、B、C三艘軍艦要同時開始鳴放禮炮各21響。已知A艦每隔5秒放1次,B艦每隔6秒放1次,C艦每隔7秒放1次。假設各炮手對時間的掌握非常準確,請編程計算觀衆總共可以聽到幾次禮炮聲。
#include <stdio.h>
int main()
{
int cnt = 0;
int t;
for(t = 0; t <= 140; t++)
{
if(t%5 == 0&& t <= 5*20)
{
cnt++;
continue;
}
if(t%6 == 0&& t <= 6*20)
{
cnt++;
continue;
}
if(t%7 == 0)
{
cnt++;
}
}
printf("n=%d",cnt);
return 0;
}
5. 水手分椰子
題目內容:
n(1<n<=5)個水手在島上發現一堆椰子,先由第1個水手把椰子分爲等量的n堆,還剩下1個給了猴子,自己藏起1堆。然後,第2個水手把剩下的n-1堆混合後重新分爲等量的n堆,還剩下1個給了猴子,自己藏起1堆。以後第3、4個水手依次按此方法處理。最後,第n個水手把剩下的椰子分爲等量的n堆後,同樣剩下1個給了猴子。請用迭代法編程計算並輸出原來這堆椰子至少有多少個,n的值要求從鍵盤輸入。若輸入的n值超出要求的範圍,程序輸出"Error!"。
提示: 分成的等量的堆數應該與水手的數量一致.
#include <stdio.h>
int coconut(int n);
int main()
{
int n;
printf( "Input n(1<n<=5):\n");
scanf("%d",&n);
printf("y=%d\n",coconut(n));
return 0;
}
int coconut(int n)
{
int i = 1;
float x = 1,y;
y = n * x + 1;
do
{
y = y * n / (n - 1) + 1;
i++;
if(y!=(int)y)
{
x++;
y = n * x + 1;
i = 1;
}
}while(i < n);
return (int)y;
}
6. 遞歸法計算遊戲人員的年齡
題目內容:
題目內容:
有n個人圍坐在一起,問第n個人多大年紀,他說比第n-1個人大2歲;問第n-1個人,他說比第n-2個人大2歲,…,問第3個人,他說比第2個人大2歲;問第2個人,他說比第1個人大2歲。第1個人說自己10歲,問第n個人多大年紀。
遞歸函數原型: unsigned int ComputeAge(unsigned int n);
#include <stdio.h>
unsigned int ComputeAge(unsigned int n);
int main()
{
unsigned int n;
scanf("%u",&n);
printf("The person's age is %u\n",ComputeAge(n));
return 0;
}
unsigned int ComputeAge(unsigned int n)
{
if(n == 1)return 10;
else
return ComputeAge(n - 1) + 2;
}
7. 遞歸法計算兩個數的最大公約數
題目內容:
利用最大公約數的性質計算。對正整數a和b,當a>b時,若a中含有與b相同的公約數,則a中去掉b後剩餘的部分a-b中也應含有與b相同的公約數,對a-b和b計算公約數就相當於對a和b計算公約數。反覆使用最大公約數的上述性質,直到a和b相等爲止,這時,a或b就是它們的最大公約數。這三條性質,也可以表示爲:
性質1 如果a>b,則a和b與a-b和b的最大公約數相同,即Gcd(a, b) = Gcd(a-b, b)
性質2 如果b>a,則a和b與a和b-a的最大公約數相同,即Gcd(a, b) = Gcd(a, b-a)
性質3 如果a=b,則a和b的最大公約數與a值和b值相同,即Gcd(a, b) = a = b
#include <stdio.h>
int Gcd(int a,int b);
int main()
{
int a,b;
printf("Input a,b:");
scanf("%d,%d",&a,&b);
if(Gcd(a,b) == 0)
printf("Input error!\n");
else
printf("%d\n",Gcd(a,b));
return 0;
}
int Gcd(int a,int b)
{
if(a <= 0 || b <= 0)
return 0;
if(a == b)
return a;
else if(a > b)
return Gcd(a - b,b);
else
return Gcd(a,b - a);
}
8. 尋找中位數v1.0
題目內容:
編寫一個函數返回三個整數中的中間數。函數原型爲: int mid(int a, int b, int c);
函數功能是 返回a,b,c三數中大小位於中間的那個數。
#include<stdio.h>
int mid(int a, int b, int c);
int main()
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
printf("The result is %d\n",mid(a,b,c));
return 0;
}
int mid(int a, int b, int c)
{
int low,temp1 = a<b?a:b;
low = temp1 < c? temp1:c;
int high ,temp2= a>b?a:b;
high = temp2 > c?temp2:c;
return a+b+c-low-high;
}
8. 還原算術表達式
題目內容:
編寫程序求以下算式中XYZ的值,其中兩數XYZ與YZZ相加的和n(99<n<1000)的值要求從鍵盤輸入。
#include<stdio.h>
int main()
{
int x,y,z,flag = 0;
int n;
printf("Input n(n<1000):\n");
scanf("%d",&n);
for(x = 1; x <= 9; x++)
{
if(flag == 0)
for(y = 1; y <= 9; y++)
{
if((n - 100*x - 110*y)%12 == 0&&(n-100*x-110*y)/12 > 0)
{
printf("X=%d,Y=%d,Z=%d\n",x,y,(n-100*x-110*y)/12);
flag = 1;
}
}
}
if(flag == 0)
printf("Invalid\n");
return 0;
}