【4.76】參考答案:
#include "stdio.h"
int a[20],b[20];
main()
{ int t=0,*m,*n,*k,*j,z,i=0;
printf("Input number 1:");
do
{ a[++t]=getchar()-'0';
}while(a[t]!=-38);
printf("Input number 2:");
do
{ b[++i]=getchar()-'0';
}while(b[i]!=-38);
if(t>i)
{ m=a+t;n=b+i;j=a;k=b;z=i;
}
else
{ m=b+i;n=a+t;j=b;k=a;z=t;
}
while(m!=j)
{ (*(--n-1))+=(*(--m)+*n)/10;
*m=(*m+*n)%10;
if(n==k+1 && *k!=1 ) break;
if(n==k+1 && *k)
{ n+=19;*(n-1)=1;
}
if(n>k+z && *(n-1)!=1) break;
}
while(*(j++)!=-38) printf("%d",*(j-1));
printf("\n");
}
【4.77】參考答案:
#include "stdio.h"
int a[20],b[20],c[40];
main()
{ int t=0,*m,*n,*k,f,e=0,*j,i=0;
printf("Input number 1:");
do
{ a[++t]=getchar()-'0';
}while(a[t]!=-38);
printf("Input number 2:");
do
{ b[++i]=getchar()-'0';
}while(b[i]!=-38);
j=c;
for(m=a+t-1;m>=a+1;m--,e++)
{ j=c+e;
for(n=b+i-1;n>=b+1;n--)
{ f=*j+*m * *n;
*(j++)=f%10;
*j+=f/10;
}
}
while(j>=c) printf("%d",*(j--)) ;
printf("\n");
}
【4.78】這是一個使用數(shù)組解決較復(fù)雜問題的典型題目。
棋盤如左圖所示,圖中箭頭表示一個棋子從[1、1]點跳到[2、3]點。為了下面敘述的方便,將I、J表示棋子起跳點的行、列號,X、Y表示落子點的行、列號。
首先我們討論如何從起跳點坐標(biāo)求出可能的落子點的坐標(biāo)。
從某點起跳,棋子最多可能有八個落子點,例如從I=3、J=5點起跳,八個可能的落子點的坐標(biāo)是[4、5]、[5、4]、[5、2]、[4、1]、[2、1]、[1、2]、[1、4]、[2、5]。將起落點的行列坐標(biāo)分開考慮,則由起點的行坐標(biāo)分別與下列八個數(shù)相加,就可得到可能的八個落子點的行坐標(biāo):1、2、2、1、-1、-2、-2、-1,將這八個數(shù)存入數(shù)組b,即:
b[]={1,2,2,1,-1,-2,-2,-1},
落子點的行坐標(biāo)X和起跳點行坐標(biāo)有如下關(guān)系:
X=b[k]+I 1≤k≤8
如果由上式計算得到的落子點X的坐標(biāo)值小于0或大于8,則表示落在了棋盤之外,應(yīng)予舍棄。
同理得到起落點之間的列坐標(biāo)關(guān)系數(shù)組是:
d[]={2,1,-1,-2,-2,-1,1,2}。
我們再討論落子點的度數(shù)問題。對于棋盤中的某一點來說,周圍最多有8個方向的棋子在這個點落子,把可能的落子數(shù)稱為度數(shù),棋盤上各點的度數(shù)如下圖所示。
根據(jù)題意,一個點只能落子一次,所以落過子的點的度數(shù)應(yīng)記為0,可跳向度數(shù)為0點的度數(shù)相應(yīng)要減1。
根據(jù)上述數(shù)組,從一個起跳點出發(fā),可能求出數(shù)個可以落子點的坐標(biāo),跳棋時到底確定落在這些點中的哪一個呢?我們確定一個原則是落在度數(shù)最少的點。如果可能落子點中有兩個點的度數(shù)一樣且都為是度數(shù)最少時,取后求出的點為落子點。因此,如果改變數(shù)組b、d中數(shù)的存放順序,遇到兩個度數(shù)最少點的先后順序就要改變,整個跳棋路徑就可改變。 2 3 4 4 4 4 3 2
3 4 6 6 6 6 4 3
4 6 8 8 8 8 6 4
4 6 8 8 8 8 6 4
4 6 8 8 8 8 6 4
4 6 8 8 8 8 6 4
3 4 6 6 6 6 4 3
2 3 4 4 4 4 3 2
在下面的程序中,將起落子行列關(guān)系的兩個一維數(shù)組合并為一個二維數(shù)組,為了提高程序的可讀性,不使用下標(biāo)為0的數(shù)組元素。
參考程序:
int base[9][3]={0, 0, 0, /* 從起跳點求落腳點的基礎(chǔ)系數(shù)數(shù)組 */
0, 1, 2,
0, 2, 1,
0, 2,-1,
0, 1,-2,
0,-1,-2,
0,-2,-1,
0,-2, 1,
0,-1, 2 };
main()
{ int a[9][9],object[9][9];
int i,j,k,p,x,y,m,n,cont;
int min,rm1,rm2,rm0=1;
for(cont=1;cont>0;)
{ for(i=0;i<=8;i++) /* 保存?zhèn)點度數(shù)的數(shù)組 清零 */
for(j=0;j<=8;j++)
a[i][j]=0;
rm1=base[1][1]; /* 改變基礎(chǔ)數(shù)組元素排列順序 */
rm2=base[1][2];
base[1][1]=base[rm0][1];
base[1][2]=base[rm0][2];
base[rm0][1]= rm1;
base[rm0][2]= rm2;
for(i=1;i<=8;i++)
{ for(j=1;j<=8;j++) /* 計算各點度數(shù)存入數(shù)組a */
{ for(p=1;p<=8;p++)
{ x=i+base[p][1];
y=j+base[p][2];
if(x>=1&&x<=8&&y>=1&&y<=8)
a[x][y]++;
}
printf(" %d",a[i][j]); /* 輸出度數(shù)表 */
}
printf("\n");
}
printf("Please Input start position:line,colume=?\n");
scanf("%d,%d",&i,&j); /* 輸入起跳點坐標(biāo) */
for(k=1;k<=63;k++) /* 求棋盤上63個落步點 */
{ object[i][j]=k; /* 跳步路徑存入數(shù)組object */
min=10;
for(p=1;p<=8;p++) /* 求從當(dāng)前起跳點出發(fā)的8個可能落點 */
{ x=i+base[p][1];
y=j+base[p][2];
if(x>=1&&x<=8&&y>=1&&y<=8) /* 求出的可能落點在棋盤內(nèi) */
if(a[x][y]!=0) /* 此點沒有落過棋子 */
{ a[x][y]--; /* 由于[i、j]點落過棋子,此點度數(shù)減1 */
if(min>a[x][y]) /* 判斷當(dāng)前可能點度數(shù)是否最小 */
{ min=a[x][y]; /* 保存可能最小度數(shù)點的度數(shù) */
m=x; /* 保存可能最小度數(shù)點的坐標(biāo) */
n=y;
}
}
}
a[i][j]=0; /* 落過棋子的[i、j]點度數(shù)為零 */
i=m; /* 已求出的最小度數(shù)點為下次搜尋的起跳點 */
j=n;
}
object[i][j] = 64 ;
for(i=1;i<=8;++i) /* 輸出跳步結(jié)果路徑 */
{ for(j=1;j<=8;j++)
if(j==8) printf("%2d",object[i][j]);
else printf("%2d ",object[i][j]);
printf("\n");
if(i!=8) printf(" \n"); /* 每行輸出8個數(shù)據(jù) */
}
rm0%=8; /* 放在基礎(chǔ)數(shù)組第一位的元素循環(huán)變化 */
rm0++; /* 基礎(chǔ)數(shù)組下一元素放在第一位 */
printf("continue?(1 or 0)");
scanf("%d",&cont);
}
}
【4.79】分析:采用試探法求解。
如圖所示,用I、J表示行、列坐標(biāo)。
開始棋盤為空,對于第1個皇后先占用第一行即I=1,先試探它占用第一列J=1位置,則它所在的行、列和斜線方向都不可在放其它皇后了,用線將它們劃掉。第2個皇后不能放在J=1、2的位置,試J=3。第2個皇后占用[2、3]后,它的行列和斜線方向也不可再放其它皇后。第3個皇后不能放在J=1、2、3、4的位置,試J=5。第4個皇后可以試位置[4、2],第5個皇后試位置[5、4]。第6個皇后已經(jīng)沒有可放的位置(棋盤上所有格子都已占滿),說明前面所放位置不對。
退回到前一個皇后5,釋放它原來占用的位置[5、4],改試空位置[5、8]。然后再前進到第6個皇后,此時仍無位置可放,退回到第5個皇后,它已沒有其它位置可選擇。進一步退回到第4個皇后釋放位置[4、2]改試位置[4、7],再前進到第5個皇后進行試探,如此繼續(xù),直到所有8個皇后都選擇一個合適的位置,即可打印一個方案。
然后從第8個皇后開始,改試其它空位置,若沒有可改選的空位置,則退回到第7個皇后改試其它位置,若也沒有空位置可改,繼續(xù)退,直到有另外的空位置可選的皇后。將它原來占用的位置釋放,改占其它新位置,然后前進到下一個皇后進行試探,直到所有8個皇后都找到合適位置,又求出一個解,打印輸出新方案。按此方法可得到92個方案。
參考答案:
#define NUM 8
int a[NUM+1];
main()
{ int number,i,k,flag,nonfinish=1,count=0;
i=1;
a[1]=1;
while(nonfinish)
{ while(nonfinish && i<=NUM)
{ for(flag=1,k=1;flag && k
if(a[k]==a[i]) flag=0;
for(k=1;flag && k
if((a[i]==a[k]-(k-i)) || (a[i]==a[k]+(k-i))) flag=0;
if(! flag)
{ if(a[i]==a[i-1])
{ i--;
if(i>1 && a[i]==NUM) a[i]=1;
else if(i==1 && a[i]==NUM) nonfinish=0;
else a[i]++;
}
else if(a[i]==NUM) a[i]=1;
else a[i]++;
}
else if( ++i<=NUM )
if(a[i-1]==NUM) a[i]=1;
else a[i]=a[i-1]+1;
}
if(nonfinish)
{ printf("\n%2d:",++count);
for(k=1;k<=NUM;k++)
printf(" %d",a[k]);
if(a[NUM-1]
else a[NUM-1]=1;
i=NUM-1;
}
}
}
【4.80】參考答案:
double findy(float x)
{ if(x>=0 && x<2)
retuen(2.5-x);
else if(x>=2 && x<4)
return(2-1.5*(x-3)*(x-3)); else if(x>=4 && x<6)
return(x/2.0-1.5);
}
main()
{ float x;
printf("Please enter x:");
scanf("%f",&x);
if(x>=0 && x<6)
printf("f(x)=%f\n",findy(x));
else
printf("x is out!\n");
}
【4.81】注釋:此程序采用模擬手工方式,對分數(shù)進行通分后比較分子的大小。
參考答案:
main( )
{ int i, j, k, l, m, n;
printf("Input two FENSHU :\n");
scanf("%d/%d,%d/%d", &i, &j, &k, &l); /* 輸入兩個分數(shù) */
m = zxgb(j,l)/j * i; /* 求出第一個分數(shù)通分后的分子 */
n = zxgb(j,l)/l * k; /* 求出第二個分數(shù)通分后的分子 */
if(m>n )
printf("%d/%d > %d/%d\n",i,j,k,l); /* 比較分子的大小 */
else if(m==n)
printf("%d/%d = %d/%d\n",i,j,k,l); /* 輸出比較的結(jié)果 */
else printf("%d/%d < %d/%d\n",i,j,k,l);
}
zxgb(a,b)
int a,b;
{ long int c;
int d;
if(a
for( c=a*b; b!=0; ) /* 用輾轉(zhuǎn)相除法求a和b的最大公約數(shù) */
{ d=b; b=a%b; a=d;
}
return((int) c/a); /* 返回最小公倍數(shù) */
}
【4.82】參考答案:
main()
{ int a[5],i,t,k;
for (i=100;i<1000;i++)
{ for(t=0,k=1000;k>=10;t++)
{ a[t]=(i%k)/(k/10);
k/=10;
}
if(f(a[0])+f(a[1])+f(a[2])==i)
printf("%d ",i);
}
}
f(m)
int m;
{ int i=0,t=1;
while(++i<=m) t*=i;
return(t);
}
【4.83】分析:任取兩個平方三位數(shù)n和n1,將n從高向低分解為a、b、c,將n1從高到低分解為x、y、z。判斷ax、by、cz是否均為完全平方數(shù)。
參考答案:
main( )
{ void f( );
int i,t,a[3],b[3];
printf("The possible perfect squares combinations are:\n");
for(i=11;i<=31;i++) /* 窮舉平方三位數(shù)的取值范圍 */
for(t=11;t<=31;t++)
{ f(i*i,a); /* 分解平方三位數(shù)的各位,每位數(shù)字分別存入數(shù)組中 */
f(t*t,b);
if(sqrt(a[0]*10+b[0])==(int)sqrt(a[0]*10+b[0])
&& sqrt(a[1]*10+b[1])==(int)sqrt(a[1]*10+b[1])
&& sqrt(a[2]*10+b[2])==(int)sqrt(a[2]*10+b[2]))
/* 若三個新的數(shù)均是完全平方數(shù) */
printf(" %d and %d\n",i*i,t*t); /* 則輸出 */
}
}
void f(n,s) /* 分解三位數(shù)n的各位數(shù)字,將各個數(shù)字 */
int n, *s; /* 從高到低依次存入指針s所指向的數(shù)組中 */
{ int k;
for(k=1000;k>=10;s++)
{ *s = (n%k)/(k/10);
k /= 10;
}
}
【4.84】參考答案:
main()
{ int i,j,l,n,m,k,a[20][20];
printf("Please enter n,m=");
scanf("%d,%d",&n,&m);
for(i=0;i
for(j=0;j
{ printf("a[%d][%d]=",i,j);
scanf("%d",&a[i][j]);
}
for(i=0;i
{ for(j=0;j
printf("%6d",a[i][j]);
printf("\n");
}
for(i=0;i
{ for(j=0,k=0;j
if(a[i][j]>a[i][k]) k=j; /* 找出該行最大值 */
for(l=0;l
if(a[l][k]
if(l>=n) /* 沒有比a[i][k]小的數(shù),循環(huán)變量l就超過最大值 */
printf("Point:a[%d][%d]==%d",i,k,a[i][k]);
}
}
【4.85】分析:按題目的要求進行分析,數(shù)字1一定是放在第一行第一列的格中,數(shù)字6一定是放在第二行第三列的格中。在實現(xiàn)時可用一個一維數(shù)組表示,前三個元素表示第一行,后三個元素表示第二行。先根據(jù)原題初始化數(shù)組,再根據(jù)題目中填寫數(shù)字的要求進行試探。
參考答案:
#include
int count; /* 計數(shù)器 */
main( )
{ static int a[ ]={1,2,3,4,5,6}; /* 初始化數(shù)組 */
printf("The possible table satisfied above conditions are:\n");
for(a[1]=a[0]+1;a[1]<=5;++a[1]) /* a[1]必須大于a[0] */
for(a[2]=a[1]+1;a[2]<=5;++a[2]) /* a[2]必須大于a[1] */
for(a[3]=a[0]+1;a[3]<=5;++a[3]) /* 第二行的a[3]必須大于a[0] */
for(a[4]=a[1]>a[3]?a[1]+1:a[3]+1;a[4]<=5;++a[4])
/* 第二行的a[4]必須大于左側(cè)a[3]和上邊a[1] */
if(jud1(a))
print(a); /* 如果滿足題意,打印結(jié)果 */
}
jud1(s) /* 判斷數(shù)組中的數(shù)字是否有重復(fù)的 */
int s[ ];
{ int i,l;
for(l=1;l<4;l++)
for(i=l+1;i<5;++i)
if(s[l]==s[i])
return(0); /* 若數(shù)組中的數(shù)字有重復(fù)的,返回0 */
return(1); /* 若數(shù)組中的數(shù)字沒有重復(fù)的,返回1 */
}
print(u)
int u[ ];
{ int k;
printf("\nNo.:%d", ++count);
for(k=0;k<6;k++)
if(k%3==0) /* 輸出數(shù)組的前三個元素作為第一行 */
printf("\n %d ",u[k]);
else /* 輸出數(shù)組的后三個元素作為第二行 */
printf("%d ",u[k]);
}
【4.86】參考答案:
#include "string.h"
strcmbn(a,b,c) /* 數(shù)組合并函數(shù):將數(shù)組a、b合并到 */
char a[],b[],c[];
{ char tmp;
int i,j,k,m,n;
m=strlen(a);
n=strlen(b);
for(i=0;i
{ for(j=i+1,k=i;j
if(a[j]
tmp=a[i]; a[i]=a[k]; a[k]=tmp;
}
for(i=0;i
{ for(j=i+1,k=i;j
if(b[j]
tmp=b[i]; b[i]=b[k]; b[k]=tmp;
}
i=0;j=0;k=0;
while(i
if(a[i]>b[j])
c[k++]=b[j++]; /* 將a[i]、b[j]中的小者存入c[k] */
else
{ c[k++]=a[i++];
if(a[i-1]==b[j]) j++; /* 如果a、b當(dāng)前元素相等,刪掉一個 */
}
while(i
while(j
c[k]='\0';
}
【4.87】參考答案:
pxn(x,n)
float x;
int n;
{ if(n==0) return(1);
else if(n==1) return(x);
else return(((2*n-1)*x*pxn(x,n-1)-(n-1)*pxn(x,n-2))/2);
}
【4.88】參考答案:
#include "stdio.h"
strout(s)
char *s;
{ if(*s!='\0')
{ strout(s+1); /* 遞歸調(diào)用strout函數(shù),字符串首地址前移一個字符 */
putch(*s); /* 輸出字符串首地址所指向的字符 */
}
else return; /* 遇到字符串結(jié)束標(biāo)志結(jié)束遞歸調(diào)用 */
}
【4.89】參考答案:楊輝三角形中的數(shù),正是(x+y)的N次方冪展開式中各項的系數(shù)。本題作為程序設(shè)計中具有代表性的題目,求解的方法很多(可以使用一維數(shù)組,也可以使用二維數(shù)組),前面我們給出用數(shù)組的答案,這里給出一種使用遞歸求解的方法。
從楊輝三角形的特點出發(fā),可以總結(jié)出:
、 第N行有N+1個值(設(shè)起始行為第0行);
⑵ 對于第N行的第J個值: (N>=2)
當(dāng)J=1或J=N+1時: 其值為1
當(dāng)J!=1且J!=N+1時: 其值為第N-1行的第J-1個值與第N-1行第J個值之和。
將這些特點提煉成數(shù)學(xué)公式可表示為:
c(x,y) = 1 x=1 或 x=N+1
c(x,y) = c(x-1,y-1) + c(x-1,y) 其它
下面給出的程序就是根據(jù)以上遞歸的數(shù)學(xué)表達式編制的。
參考答案:
#include
main( )
{ int i,j,n=13;
printf("N=");
while( n>12 )
scanf("%d", &n); /* 最大輸入值不能大于12 */
for(i=0;i<=n;i++) /* 控制輸出N行 */
{ for(j=0;j<12-i;j++)
printf(" "); /* 控制輸出第i行前面的空格 */
for(j=1;j
printf("%6d", c(i,j)); /* 輸出第i行的第j個值 */
printf("\n");
}
}
int c(x,y) /* 求楊輝三角形中第x行第y列的值 */
int x, y;
{ int z;
if((y==1)||(y==x+1))
return(1); /* 若為x行的第1或第x+1列,則輸出1 */
else /* 否則;其值為前一行中第y-1列與第y列值之和 */
z = c(x-1,y-1) + c(x-1,y);
return(z);
}
【4.90】分析:整型數(shù)在計算機中就是以二進制形式存儲的,此題的目的僅是為了學(xué)習(xí)遞歸程序的編程。
參考答案:
turn(n,a,k)
int n,a[ ],k;
{ if(n>0)
{ a[k]=n%2;
turn(n/2,a,k-1);
}
else return;
}
main()
{ int i,n,a[16]={0};
printf("\nPlease enter n:");
scanf("%d",&n);
turn(n,a,15);
for(i=0;i<16;i++)
printf("%d",a[i]);