程式設計方法學-上機
要求
一、完成內容包含以下內容:
1.題目分析
2.演算法構造
在此論證演算法設計中的一些必要的設計依據。
3.演算法實現
程式原始碼(請寫入必要的註釋)。
4.執行結果
5.經驗歸納
1.一個人趕著鴨子去每個村莊賣,每經過一個村子賣去所趕鴨子的一半又一隻。這樣他經過了七個村子後還剩兩隻鴨子,問他出發時共趕多少隻鴨子?經過每個村子賣出多少隻鴨子?
(1)題目分析:
設經過第n個村子時有count(n)只鴨子,賣去count(n)/2+1只鴨子,剩下count(n+1 )只鴨子,則有count(n)=count(n)/2+1+count(n+1),即count(n)=2*(count(n+1)+1)。經過第8個村子時有2只鴨子,即count(8)=2。出發時共趕count(1)只鴨子,經過第n個村子時賣出count(n)/2+1只鴨子。
count(n)=2*(count(n+1)+1),1<=n<8
count(n)=2, n=8
(2)程式原始碼:
#include<iostream> using namespace std; int count(int n) //經過第n個村子之前有count(n)只鴨子 { if(n==8)//遞迴出口 return 2; else return 2*(count(n+1)+1);//遞迴體 } void main() { cout<<"出發時共趕"<<count(1)<<"只鴨子"<<endl; for(int i=1;i<8;i++) { cout<<"經過第"<<i<<"個村子賣出"<<count(i)/2+1<<"只鴨子"<<endl; } }
2.角谷定理。輸入一個自然數,若為偶數,則把它除以2,若為奇數,則把它乘以3加1。經過如此有限次運算後,總可以得到自然數值1。求經過多少次可得到自然數1。
如:輸入22,
輸出 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
STEP=16
(1)題目分析:
當x等於1時,輸出step;當x為偶數時,step=step+1;當x為奇數時,step=step+1。
(2)程式原始碼:
#include <stdio.h> void Function(int *step,int n) //因為傳入的引數需要經過變化所以一定要用指標!! { if(n == 1) { printf("%d",n); return ; } if( n % 2 == 0) { printf("%d ",n); (*step)++; //自加的優先順序比*更高所以必須加上括號 Function(step,n / 2); }else if(n % 2 != 0) { printf("%d ",n); (*step)++; Function(step,3 * n + 1); } } int main () { int n; int step = 0; printf("請輸入您的數字:\n"); scanf("%d",&n); printf("變化過程:"); Function(&step,n); printf("\n"); printf("總共的步數:%d",step); printf("\n"); return 0; }
3.電話號碼對應的字元組合:在電話或者手機上,一個數字如2對應著字母ABC,7對應著PQRS。那麼數字串27所對應的字元的可能組合就有3*4=12種(如AP,BR等)。現在輸入一個3到11位長的電話號碼,請打印出這個電話號碼所對應的字元的所有可能組合和組合數。
#include<stdio.h>
#include<string.h>
#define M 12
#define N 30
int a[M];
char b[28]={'*','#','A','B','C','D','E','F','G','H','I',
'J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
char c[10][10]={'*','#','ABC','DEF','GHI','JKL','MNO','PORS','TUV','WXYZ'};
int i,n;
int GroupNum(int x)
{
if(i==n)
return x;
else
{
if(a[i]==0||a[i]==1)
{
x=1*x;
i++;
GroupNum(x);
}
else if(a[i]==2||a[i]==3||a[i]==4||a[i]==5||a[i]==6||a[i]==7||a[i]==8)
{
x=3*x;
i++;
GroupNum(x);
}
else
{
x=4*x;
i++;
GroupNum(x);
}
}
}
int main()
{
printf("輸入號碼的總位數");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("請輸入號碼的第%d位",i+1);
scanf("%d",&a[i]);
}
i=0;
printf("此號碼對應的字元號碼組合共有%d組\n",GroupNum(1));
return 0;
}
4.日本著名數學遊戲專家中村義作教授提出這樣一個問題:父親將2520個桔子分給六個兒子。分完 後父親說:“老大將分給你的桔子的1/8給老二;老二拿到後連同原先的桔子分1/7給老三;老三拿到後連同原先的桔子分1/6給老四;老四拿到後連同原先的桔子分1/5給老五;老五拿到後連同原先的桔子分1/4給老六;老六拿到後連同原先的桔子分1/3給老大”。結果大家手中的桔子正好一樣多。問六兄弟原來手中各有多少桔子?
(1)題目分析:
每個兒子的橘子數目有兩種,原有的和現有的,除了老大,其他的兒子原有的+別人給的-給別人的=現有的=平均數,所以原有的=現有的+給別人的-別人給的。大兒子得到六兒子之前的是:大兒子原有的-給二兒子的(1/8)=現有的-別人給的(六二子給的);六兒子現有的(ave)=(六兒子原有的+別人給的)*(2/3),所以,( 7/8*大兒子原有的)=現有的-六兒子給的,所以大兒子現有的=得到六兒子之前的8/7倍。 拿二兒子作說明:老二拿到後連同原先的桔子分1/7給老三。(原有的+拿到的)*6/7=ave,所以give=(原有的+拿到的)*1/7=ave*6/7*1/7=give=ave/(8-i-1)(此時i為1) 每個兒子現有的和原有的關係為: a[i]=a[i]+(a[i]/(8-i-1))-(a[i-1]/(8-(i-1)-1))
(2)程式原始碼
#include<iostream>
using namespace std;
int main()
{
int a[6];//存放六個兒子原先手中的橘子數目
int left = 0;//存放下一個兒子得到的橘子數目
int ave = 420;
for(int i=0;i<6;i++)
{
if(i==0)
{
a[i]=(ave-ave/2)*(8-i)/(8-i-1);//第一個兒子的數目,
left=a[i]-ave/2;
}
else
{
a[i]=ave*(8-i)/(8-i-1)-left;//由left求第i+1個兒子的橘子數目
left=ave/(8-i-1);//第i+1個兒子得到的橘子數目
}
}
for(int x=0;x<6;x++)
{
cout<<"第"<<i+1<<"個兒子原先手中的橘子數目數為"<<a[i]<<endl;//輸出每個兒子原先手中的橘子數目
}
return 0;
}