首页 > 编程 > C++ > 正文

2012年第三届蓝桥杯C/C++组真题训练(二)(2017.2.8)

2019-11-11 00:33:18
字体:
来源:转载
供稿:网友

5. (6')代码填空

对一个方阵转置,就是把原来的行号变列号,原来的列号变行号

例如,如下的方阵:

 1 2  3  4

 5 6  7  8

 9 10 11 12

13 14 15 16

转置后变为:

 1 5  9 13

 2  6 1014

 3  7 1115

 4  8 1216

但,如果是对该方阵顺时针旋转(不是转置),却是如下结果:

13  9 5  1

14 10  6  2

15 11  7  3

16 12  8  4

下面的代码实现的功能就是要把一个方阵顺时针旋转。

填空后代码:

#include <stdio.h>#include <stdlib.h>void rotate(int* x, int rank){	int* y = (int*)malloc(rank*sizeof(x));            // 填空	int i;	for(int i=0; i<rank * rank; i++)	{		y[rank -1 - i/rank + rank * (i%rank)] = x[i];       // 填空	}	for(i=0; i<rank*rank; i++)	{		x[i] = y[i];	}	free(y);}int main(int argc, char* argv[]){	int x[4][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};	int rank = 4;	rotate(&x[0][0], rank);	for(int i=0; i<rank; i++)	{		for(int j=0; j<rank; j++)		{			PRintf("%4d", x[i][j]);		}		printf("/n");	}	return 0;}程序截图:

6. (9')代码填空

        对于32位字长的机器,大约超过20亿,用int类型就无法表示了,我们可以选择int64类型,但无论怎样扩展,固定的整数类型总是有表达的极限!如果对超级大整数进行精确运算呢?一个简单的办法是:仅仅使用现有类型,但是把大整数的运算化解为若干小整数的运算,即所谓:“分块法”。

        如图【1.jpg】表示了分块乘法的原理。可以把大数分成多段(此处为2段)小数,然后用小数的多次运算组合表示一个大数。可以根据int的承载能力规定小块的大小,比如要把int分成2段,则小块可取10000为上限值。注意,小块在进行纵向累加后,需要进行进位校正。

        以下代码示意了分块乘法的原理(乘数、被乘数都分为2段)。

填空后代码:

#include <stdio.h>void bigmul(int x, int y, int r[]){	int base = 10000;	int x2 = x / base;	int x1 = x % base; 	int y2 = y / base;	int y1 = y % base; 	int n1 = x1 * y1; 	int n2 = x1 * y2;	int n3 = x2 * y1;	int n4 = x2 * y2;	r[3] = n1 % base;	r[2] = n1 / base + n2 % base + n3 % base;	r[1] = n2 / base + n3 / base + n4 % base; // 填空	r[0] = n4 / base;		r[1] += r[2] / base;                      // 填空	r[2] = r[2] % base;	r[0] += r[1] / base;	r[1] = r[1] % base;}int main(int argc, char* argv[]){	int x[] = {0,0,0,0};	bigmul(87654321, 12345678, x);	printf("%d%d%d%d/n", x[0],x[1],x[2],x[3]);	return 0;}程序截图:

7. (13')代码填空

        今有 6 x 6 的棋盘格。其中某些格子已经预先放好了棋子。现在要再放上去一些,使得:每行每列都正好有3颗棋子。我们希望推算出所有可能的放法。下面的代码就实现了这个功能。

        初始数组中,“1”表示放有棋子,“0”表示空白。

填空后代码:

#include <stdio.h>int N = 0;bool CheckStoneNum(int x[][6]){	for(int k=0; k<6; k++)	{		int NumRow = 0;		int NumCol = 0;		for(int i=0; i<6; i++)		{			if(x[k][i]) NumRow++;			if(x[i][k]) NumCol++;		}		if(NumRow!=3 || NumCol!=3) return false;  // 填空	}	return true;}int GetRowStoneNum(int x[][6], int r){	int sum = 0;	for(int i=0; i<6; i++) 	if(x[r][i]) sum++;	return sum;}int GetColStoneNum(int x[][6], int c){	int sum = 0;	for(int i=0; i<6; i++) 	if(x[i][c]) sum++;	return sum;}void show(int x[][6]){	for(int i=0; i<6; i++)	{		for(int j=0; j<6; j++) printf("%2d", x[i][j]);		printf("/n");	}	printf("/n");}void f(int x[][6], int r, int c);void GoNext(int x[][6],  int r,  int c){	if(c<6)		f(x, r, c+1);   // 填空	else		f(x, r+1, 0);}void f(int x[][6], int r, int c){	if(r==6)	{		if(CheckStoneNum(x))		{			N++;			show(x);		}		return;	}	if(x[r][c])  // 已经放有了棋子	{		GoNext(x,r,c);		return;	}		int rr = GetRowStoneNum(x,r);	int cc = GetColStoneNum(x,c);	if(cc>=3)  // 本列已满		GoNext(x,r,c);  	else if(rr>=3)  // 本行已满		f(x, r+1, 0);   	else	{		x[r][c] = 1;		GoNext(x,r,c);		x[r][c] = 0;				if(!(3-rr >= 6-c || 3-cc >= 6-r))  // 本行或本列严重缺子,则本格不能空着!			GoNext(x,r,c);  	}}int main(int argc, char* argv[]){	int x[6][6] = {		{1,0,0,0,0,0},		{0,0,1,0,1,0},		{0,0,1,1,0,1},		{0,1,0,0,1,0},		{0,0,0,1,0,0},		{1,0,1,0,0,1}	};	f(x, 0, 0);		printf("%d/n", N);	return 0;}程序截图:


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选