1.下面的程序运行结果是什么?(p36)
#include<stdio.h>
int main()
{
double i;
for(i=9.9;i!=10;i+=0.1)
{
printf("%.lf\n",i);
}
return 0;
}
根据自己主观感觉,以为结果是9.9
运行发现是
10
10
10
10
10
10
10
11
11
11
11
11
11
11
11
11
11
12
12
12
。。。。
无限循环下去了
再仔细思索 发现两个问题
①double类型的数值进行运算得不到“数学上精确”的结果(详见点击打开链接)
②按%.lf输出,结果是忽略小数点后面的部分的
而按%x.ylf输出的话,结果是总共占x位,保留y位小数
接着稍稍改了代码,将for语句中的初始化语句改成i=10,运行结果不再无限循环了,也没输出
2.开灯问题(p39)
分析:此题有一个特点:若数量较少时,人可以不借助任何外物就可以解决,但一旦数量过大,单凭人力就有些吃力了,所以就可以借助计算机超凡的计算力来“模拟”问题情境,从而解决问题。用a[1],a[2],a[3],... ,a[n]表示编号为1,2,3,...,n的灯是否开着,开闭状态可以用0和1表示。开关动作可以用取反来模拟(!0=1,!1=0)
代码如下:
#include<stdio.h>
#include<string.h> //下面的memset函数所需的头文件
#define maxn 1010
int a[maxn];
int main()
{
int n,k,first=1;
memset(a,0,sizeof(a)); //将数组a中的元素初始化为0
scanf("%d%d",&n,&k);
for(int i=1;i<=k;i++)
for(int j=1;j<=n;j++)
if(j%i==0) a[j]=!a[j];
for(int i=1;i<=n;i++)
if(a[i]) {
if(first)
first=0; //输出时保持空格,即除了第一个数,其余所有的数输出之前都先输出一个空格
else
printf(" ");
printf("%d",i);
}
printf("\n");
return 0;
}
3.蛇形填数(P39)
题目:在n*n方阵里填入1,2,。。。,n*n,要求填成蛇形。例如,n=4时方阵为:
10 11 12 1
9 16 13 2
8 15 14 3
7 6 5 4(方阵中,多余的空格不必严格输出。n<=8)
分析:同上一题特点一样,此题可以通过“模拟”来解。仔细分析,“笔”的移动轨迹为:下,下,下,左,左,左,上,上,上,右,右,下,下,左,上
容易发现都是四个过程一个循环(先下,再左,再上,最后右)。而且每次转向无非两种情况:一是再走就出界(如从4到5),二是再走就要走到以前走的格子(如从12到13)
第一种情况可以轻易判断,而第二种情况可以通过先将二维数组全部初始化为0,通过数组中元素是否为零判断是否已经填过
代码如下:
#include<stdio.h>
#include<string.h>
#define maxn 20
int a[maxn][maxn];
int main()
{
int n,x,y,tot=0;
scanf("%d",&n);
memset(a,0,sizeof(a));
x=0;
y=n-1;
a[x][y]=1;
tot=1;
while(tot<n*n)
{
while(x+1<n&&!a[x+1][y]) a[++x][y]=++tot;
while(y-1>=0&&!a[x][y-1]) a[x][--y]=++tot;
while(x-1>=0&&!a[x-1][y]) a[--x][y]=++tot;
while(y+1<n&&!a[x][y+1]) a[x][++y]=++tot;
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
printf("%3d",a[i][j]);
printf("\n");
}
return 0;
}
ps:四条while语句都遵循一个原则,就是先判断,后赋值,而不是赋完值再判断,因为若是出错,很难修改回来
提示:很多情况下,最好是在做一件事之前检查是不是可以做,而不要做完再后悔,因为“悔棋”往往比较麻烦