# 算法设计与分析-----第三章课后习题

（3）编程打印如图3-5所示的n×n方阵。

//算法一：
#include <stdio.h>
int a[100][100];
int main(){
int n;
int i, j;
int x = 1;
scanf("%d", &n);
for(i = 1; i <= n/2; i++){
for(j = i; j <= n-i+1; j++){
a[i][j] = x;
x++;
}
for(j = i+1; j <= n-i+1; j++){
a[j][n-i+1] = x;
x++;
}
for(j = n-i; j >= i; j--){
a[n-i+1][j] = x;
x++;
}
for(j = n-i; j >= i+1; j--){
a[j][i] = x;
x++;
}
}
if(n%2 == 1) a[n/2+1][n/2+1] = x;
for(i = 1; i <= n; i++){
for(j = 1; j <= n; j++){
printf("%3d", a[i][j]);
}
printf("\n");
}
return 0;
}
//算法二：
#include <stdio.h>
int a[100][100];
int main(){
int i, j, k, n, b[2], x, y, t;
scanf("%d", &n);
b[0] = 0;
b[1] = 1;
k = n;
t = 1;
x = 1;
while(x <= n*n){
for(y = 1; y <= 2*k-1; y++){
b[y/(k+1)] = b[y/(k+1)] + t;
a[b[1]][b[0]] = x;
x++;
}
k--;
t = -t;
}
for(i = 1; i <= n; i++){
for(j = 1; j <= n; j++){
printf("%3d", a[i][j]);
}
printf("\n");
}
return 0;
}

（4）编程打印如图3-6所示的n×n方阵的上三角阵。

#include <iostream>
using namespace std;
int a[100][100];
int main(){
int n, i, j;
int x = 1;
cin >> n;
for(i = 1; i <= n; i++){
for(j = 1; j <= i; j++){
a[i-j+1][j] = x;
x++;
}
}

for(i = 1; i <= n; i++){
for(j = 1; j <= n-i+1; j++){
cout << a[i][j] <<" ";
}
cout << endl;
}
return 0;
} 

(9)有一只经过训练的蜜蜂只能爬向右侧相邻的蜂房，，不能反向爬行。如图3-9试求出蜜蜂从蜂房a爬到蜂房b的可能路线数（0<a<b<100）。

#include<stdio.h>
int f(int x){
if(x==2) return 1;
else if(x==3) return 2;
else return f(x-2)+f(x-1);

}
int main(){
int a, b;
scanf("%d %d", &a, &b);
int c = f(b-a+1);
printf("%d", c);
return 0;
}

(17)完成给“余”猜数的游戏：

Please think of a number between 1 and 100
Your number divided by 3 has a remainder of 1
Your number divided by 4 has a remainder of 0
Your number dividedby 7 has a remainder of 5
Let me think a moment …

#include<stdio.h>
int main(){
int a, b, c, d;
scanf("%d %d %d", &a, &b, &c);
d=28*a+21*b+36*c;
while(d>84){
d -= 84;
}
printf("%d", d);
return 0;
}
/*数学模型：先看基本的数学常识。
（1）当s=u+3×v+3×w时，s除以3的余数与u除以3的余数是一样的。
（2）对s=cu+3×v+3×w，当c除以3余数位1的数时，s除以3的余数与u除以3的
余数也是一样的。证明如下：

c除以3余数为1，记c=3×k+1，则s=u+3×k×u+3×v+3×w，由（1）的结论，
上述结论正确

为了好讲解，先给出问题的数学模型，在讲解模型建立的道理。记a，b，c，分
别为所猜数距d除以3，4，7后的余数，则d=28×a+21×b+36×c为问题的数学模型，
其中28称作a的系数，21称作为b的系数，36称作为c的系数。下面来看一下建立
模型的道理。
由以上数学常识，a，b，c的系数必须满足：
（1）b、c的系数能被3整除，且a的系数被3整除余1，这样d除以3的余数与a相同。
（2）b、c的系数能被3整除，且b的系数被4整除余1，这样d除以3的余数与a相同。
（3）a、b的系数能被3整除，且c的系数被7整除余1，这样d除以3的余数与a相同。
由此可见：c的系数是3和4的公倍数且被7整除余1，正好是36；
a的系数是4和7的公倍数且被3整除余1，正好是28；
b的系数是3和7的公倍数且被4整除余1，正好是21。

算法设计：用以上模型求解的数d，可能比100打，这时只要减去3，4，7的最小
公倍数就是问题的解了

拓展：若三个除数和余数都是由用户给出，如何设计算法？
*/

（18）求这样的两个数据，5位数=2×4位数，9个数字互不相同。

#include<stdio.h>
#include<string.h>
int main(){
char s[10];
int a[10];
for(int i = 1000; i <9999; i++){
int count = 0;
int j = 2*i;
if(10000<j && j<99999){
memset(a, 0, sizeof(a));
sprintf(s,"%d%d",i,j);
for(int p=0; p<9; p++){
a[int(s[p]-'0')]++;
}
for(int p=0; p<10; p++){
if(a[p]==1) count++;
}
if(count==9) printf("%d %d\n",i ,j);
}
}

return 0;
}


Guzi499