1. 程式人生 > >程式設計方法學-上機

程式設計方法學-上機

要求

一、完成內容包含以下內容:

 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;  
}