您的位置:首页 > 其它

『算法学习笔记』23th-24th day. 数组

2014-03-12 11:18 260 查看
exa3.0

1 /**
2 * output the input numbers in reverse order.
3 */
4 #include<stdio.h>
5 #define MAXN 100 +10
6 int main()
7 {
8         int a[MAXN];
9         int i, x,n=0;
10         while (scanf("%d",&x)==1)
11         {
12                 a[n++]=x;
13         }
14         for(i=n-1;i>=1;i--) printf("%d ",a[i]);
15         printf("%d\n",a[0]);
16         return 0;
17 }


注意:

1.数组的大小往往不会精确给出,要习惯于开稍微大一点的数组--保险。

2.数组存到数组之后要注意前面N-1个数 中间用空格隔开就行,而最后一个数(行尾)应该又换行!

回忆之前的规定:

算法竞赛中每行输出最后应以回车符结束,包括最后一行。

除非特别说明,每行行首不应有空格,但行末通常可以有多余的空格。

此外,输出的两个数或者字符串之间应该用单个空格隔开。

3.把上面的程序MAXN改为1000000 会在运行时报错段错误 (核心已转储)

---》 比较大的数组应该声明在main之外!

4.数组不能够进行赋值操作 比如 int a[MAXN], b[MAXN]

不能直接a=b 而要借助memcpy()

复制整个整形数组:memcpy(b,a,sizeof(a))

复制整形数组前k个元素: memcpy(b,a,sizeof(int)*k)

复制浮点型数组前k个元素:memcpy(b,a,sizeof(double)*k)

此外使用memcpy需要包含头文件string.h

exa3-1 开灯问题

有n盏灯,编号1-n。第一个人把所有灯打开,第二个人按下所有编号为2的倍数的开关(这些灯被关),第三个人按下所有编号为3的倍数的开关。。。

以此进行下去一共有k个人,问最后有哪些灯开着? 输入n,k,输出开着的灯的编号 。 k<n<1000.

样例输入: 7 3

样例输出:1 5 6 7

1 #include<stdio.h>
2 #include<string.h>
3 #define MAXN 1000+10
4 int a[MAXN];
5 int main()
6 {
7         int i,j,n,k,first=1;
8         memset(a,0,sizeof(a));
9         scanf("%d%d", &n,&k);
10         for(i=1;i<=k;i++)
11                 for(j=1;j<=n;j++)
12                         if(j%i==0) a[j]=!a[j];
13         for(i=1;i<=n;i++)
14                 if(a[i]){if(first)first =0; else printf(" ");printf("%d",i);}
15         printf("\n");
16         return 0;
17 }


备注:

1.memset(a,0,sizeof(a)) 作用是将整个数组a初始化为0,也在string,h中定义。 比for循环赋值来的简洁!

2.为了避免输出多余空格,设置一个标志变量first 判断当前输出的变量是否为第一个。 第一个变量前不应有空格。

《我觉得其实直接每个变量后面加空格应该也是可以的。》

3.由于只有0和1两种取值,所以 a=!a是很简洁的算法。如果有两种取值0, b ,那么 a=b-0就很好!

4,注意由于灯的数量是确定的,也就是说上届是确定的,这时候的倍数关系用求余处理比较方便。如果用乘法处理会比较麻烦。

exa3-3 蛇形填数

在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.

1 #include<stdio.h>
2 #include<string.h>
3 #define MAXN 10
4 int a[MAXN][MAXN];
5 int main()
6 {
7         int n,x,y,tot=0;
8         scanf("%d",&n);
9         memset(a,0,sizeof(a));
10         tot=a[x=0][y=n-1]=1;
11         while(tot<n*n)
12         {
13                 while(x+1<n  && !a[x+1][y]) a[++x][y]=++tot;
14                 while(y-1>=0 && !a[x][y-1]) a[x][--y]=++tot;
15                 while(x-1>=0 && !a[x-1][y]) a[--x][y]=++tot;
16                 while(y+1<n  && !a[x][y+1]) a[x][++y]=++tot;
17         }
18         for(x=0;x<n;x++)
19         {
20                 for(y=0;y<n;y++)printf("%4d", a[x][y]);
21                 printf("\n");
22         }
23         return 0;
24 }


1.这段程序利用了C语言的简洁优势。

比如!a[x+1][y] 判断这个数是不是0;a[++x][y]=++tot; 同时完成赋值和x,tot的增加。

还有tot=a[x=0][y=n-1]=1 同时完成了x,y 的赋值 和tot a[0][n-1] 的赋值!

2.移动的原则是:先预判,再移动。

边界确定的时候一定要细心,再就是++放在前面还是后面也要仔细考虑。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: