2013华为第五届编程大赛 成都初赛题目和解答

本文介绍了2013年华为编程大赛成都初赛的两道题目,包括路灯统计和连连看棋盘问题。对于路灯统计,需要找出连续相同状态的路灯最大数量;连连看问题则要求判断两个坐标点的图案是否能消除,输出消除路径上的图案个数。文章提供了样例输入和输出,并提到代码实现中的一些思考。
摘要由CSDN通过智能技术生成

昨天看到今年的报名,把隔壁zy同学的去年题目拿过来做了一下,http://blog.csdn.net/zy416548283/article/details/23712151

前两个解法差不多,第三个用dfs,bfs方法可参考zy同学


1、路灯统计:

    题目描述
某省会城市街道纵横交错,为了监控路灯的运行状况,每条街道使用一个数字字符串标识该街道上所有路灯的运行状况。
假设路灯只有如下3种状态(分别用数字0, 1, 2标识,一盏路灯只对应其中一种状态):
0 标识路灯熄灭;
1 标识路灯开启;
2 标识路灯故障;
请根据输入的字符串,找出该街道上连续的处于相同状态的路灯的最大个数。若两种状态的路灯数量相同,则返回最先出现的路灯状态。
   输入:
街道上连续的路灯组成的状态字符串。字符串中只包含数字,每个路灯的状态为0,1,2中的一种状态。如“1101”代表4盏路灯,第3盏路灯为熄灭状态,其它3盏为开启状态。
   输出:
连续为相同状态的路灯的最大数量,上述路灯的状态;
要求:先输出数量,再输出状态,两个整数间采用一个空格间隔。如输出:53 2
样例输入
112200111
样例输出
3 1

#include<stdio.h>
#include<string.h>

#define MAX_LINE 1024

int main()
{
	char str[MAX_LINE], result;
	int i, max_len = -1, cur_len = 1;

	fgets(str, MAX_LINE, stdin);

	for (i = 0; str[i] != '\n'; i++)
	{
		if (str[i] == str[i+1])
			cur_len++;
		else {
			if (cur_len > max_len) {
				max_len = cur_len;
				cur_len = 1;
				result = str[i];
			}
			else if (cur_len == max_len) 
				cur_len = 1;
		}
	}
	printf("%d %c", max_len, result);

	return 0;
}

2. 求复数的平均值
    题目描述  由实部和虚部组成,形如(a,bi)这样的数,称为复数。
    通信系统中,通常用32bit数来表示复数(高16bit表示实部,低16bit表示虚部),如整数524295(16进制为0x00080007)
所代表的复数,实部为0x0008,虚部为0x0007。  有别于实数运算,复数加、减、乘、除运算定义如下: 
复数加公式:(a,bi) + (c,di) = (a + c),(b + d)i 复数减公式:(a,bi) + (c,di) = (a - c),(b - d)i  
复数乘公式:(a,bi) * (c,di) = (ac - bd),(ad + bc)i 复数除公式:(a,bi) / N = (a/N),(b/N)i  
题目要求,输入N个复数,计算这个N个复数的平均值,
复数Avg = (复数1*复数2 + 复数3*复数4 + … + 复数N-1*复数N) / N。 
 复数加、复数减、复数乘、复数除的结果仍然为复数,实部和虚部均为16bit有符号数,
计算过程中,当结果大于32767(0x7fff)时,输出32767;当计算结果小于-32768(0x8000)时,输出-32768。 
 输入  输入共计两行   有别于实数运算,复数加减乘除运算定义如下第一行包含1个整数,表示输入复数个数N(N为偶数,N不大于1000)   第一行包含1个整数,
表示输入复数个数N(N为偶数,N不大于1000)  输出  经计算得到的复数的平均值。 

 
样例输入  4  262149,393223,524297,655371 
样例输出  -458693

#include<stdio.h>

#define MAX_NUM 1024

typedef struct complx{
	int real;
	int img;
}complx;
complx comp_set[MAX_NUM];

int crossover(int m)
{
	if (m > 32767)
		return 32767;
	else if (m < -32768)
		return -32768;
	else
		return m;
}

complx convert(int m)
{
	complx c_tmp;
	c_tmp.real = (m & 0xffff0000) >> 16;
	c_tmp.img =  m & 0x0000ffff;	
	return c_tmp;
}

int re_convert(complx a)
{
	return ((a.real << 16) + a.img);
}

complx times(complx a, complx b)
{
	complx tmp;
	tmp.real = crossover(crossover(a.real*b.real) - crossover(a.img*b.img));
	tmp.img = crossover(crossover(a.real*b.img) + crossover(a.img*b.real));
	return tmp;
}

complx plus(complx a, complx b)
{
	complx tmp;
	tmp.real = crossover(a.real + b.real);
	tmp.img = crossover(a.img + b.img);
	return tmp;
}

complx div(complx a, int n)
{
	complx tmp;
	tmp.real = a.real / n;
	tmp.img = a.img / n;
	return tmp;
}	

int main()
{
	int n, i, i_tmp;
	complx sum = {0,0}, com_tmp;

	scanf("%d", &n);

	if (n % 2 != 0)
		return 0;

	for(i = 0; i < n; i++)
	{
		scanf("%d", &i_tmp);
		comp_set[i] = convert(i_tmp);
	}

	for (i = 0; i < n; i += 2)
	{
		com_tmp = times(comp_set[i], comp_set[i+1]);
		sum = plus(sum, com_tmp);
	}

	sum = div(sum, n);
	printf("%d", re_convert(sum));
	return 0;
}

3. 连连看游戏:

题目描述
连连看,你不会?那就out了!
给定一个连连看棋盘,棋盘上每个点有各种图案(用非0数字表示),输入棋盘上的任意两个坐标,判断这两个坐标对应的图案是否可以消除,消除的条件是图案相同且图案间连线的转角数不得超过2 。
1    3    3    4
0    6    0    0
4    0    2    1
6    0    4    2
图中,(0,1)和(0,2)中的3没有转角可以消去,(1,1)和(3,0)中的6有一个转角可以消去,(2,0)和(3,2)中的4有两个转角可以消去,而(0,0)和(2,3)中的1不能消去。
输入
输入为连续的整数,第1个数为棋盘行数m,第2个数为棋盘列数n,然后依次是m*n个棋盘数据(先行后列),最后,是两个坐标对应的行号和列号,m行n列的棋盘,共计输入m*n+6个数。
输出
如果图案不能消除,输出0;如果图案可以消除,输出消除路线上图案个数(包含输入的两个图案,不考虑有多条可消除路径的情况)。


样例输入

4 4 1 3 3 4 0 6 0 0 4 0 2 1 6 0 4 2 2 0 3 2

样例输出
4

//2013  HuaWei 3   simon xia 2014.4.17
#include<stdio.h>
#include<string.h>

#define MAX_ROW 50
#define MAX_COL 50

#define UP    1
#define RIGHT 2
#define DOWN  3
#define LEFT  4

typedef struct {
	int row;
	int col;
	int direction[5];
}position;

typedef struct {
	int pathlen;
	int direction;
	int dir_cha_cnt;
}pathinfo;

position stack_pos[16];
pathinfo stack_info[16];

int top_pos = -1;
int top_info = -1;
int matrix[MAX_ROW][MAX_COL];

void push_pos(position pos)
{
	stack_pos[++top_pos] = pos;
}

void push_info(pathinfo info)
{
	stack_info[++top_info] = info;
}

position pop_pos()
{
	return stack_pos[top_pos--];
}

pathinfo pop_info()
{
	return stack_info[top_info--];
}

int set_dir(int row, int col, int dir[], int m, int n, int cur_dir)
{
	if (!matrix[row][col+1] && col+1 < n && cur_dir != LEFT) dir[RIGHT] = 1;
	if (!matrix[row][col-1] && col-1 >= 0 && cur_dir != RIGHT) dir[LEFT] = 1;
	if (!matrix[row-1][col] && row-1 >= 0 && cur_dir != DOWN) dir[UP] = 1;
	if (!matrix[row+1][col] && row+1 < m && cur_dir != UP) dir[DOWN] = 1;
}

int count_path(int dir[])
{
	int count = 0, i = 0;
	for (; i < 5; i++)
		count += dir[i];
	return count;
}

int get_end(int i, int j, int end, int start_row, int start_col)
{
	if ( (matrix[i][j+1] == end && i != start_row && j+1 != start_col) 
  || (matrix[i][j-1] == end && i != start_row && j-1 != start_col)
  || (matrix[i-1][j] == end && i-1 != start_row && j != start_col)
  || (matrix[i+1][j] == end && i+1 != start_row && j != start_col))
	return 1;
	else
		return 0;
}

int main()
{
	freopen("input_h3", "r", stdin);
	int m, n, i, j, k, pathlen = 1, pathnum;
	int dir_change = 0, cur_dir = 0; 
	int dir_tmp[5] = {0};
	position a, b, pos_tmp;
	pathinfo info_tmp;

	memset(matrix, 0, sizeof(matrix));
	scanf("%d%d", &m, &n);
	for (i = 0; i < m; i++)
		for (j = 0; j < n; j++)
			scanf("%d", &matrix[i][j]);
	scanf("%d%d%d%d", &a.row, &a.col, &b.row, &b.col);
	
	if (matrix[b.row][b.col] != matrix[a.row][a.col] || matrix[a.row][a.col] == 0 || matrix[b.row][b.col] == 0)
		return 0;

	for (i = a.row, j = a.col; (!get_end(i,j,matrix[b.row][b.col],a.row,a.col)); )
	{
		if (!count_path(dir_tmp))
			set_dir(i, j, dir_tmp, m, n, cur_dir);
		pathnum = count_path(dir_tmp);

		if (!pathnum) {
			if (top_pos == -1) {
				printf("%d", 0);
				return 0;
			}
			else {
				pos_tmp = pop_pos();
				i = pos_tmp.row;
				j = pos_tmp.col;
				memcpy(dir_tmp, pos_tmp.direction, 5*sizeof(int));

				info_tmp = pop_info();
				pathlen = info_tmp.pathlen;
				cur_dir = info_tmp.direction;
				dir_change = info_tmp.dir_cha_cnt;
			}
		}else if (pathnum == 1) {
			for (k = 1; k < 5; k++)
				if (dir_tmp[k]) break;
			if (k != cur_dir)
				dir_change++;
			switch (k) {
				case 1:{i--; break;}
				case 2:{j++; break;}
				case 3:{i++; break;}
				case 4:{j--; break;}
			}
			pathlen++;
			memset(dir_tmp, 0, sizeof(dir_tmp));
		}
		else
		{
			pos_tmp.row = i;	
			pos_tmp.col = j;	
			for (k = 1; k < 5; k++)
				if (dir_tmp[k]) break;
			dir_tmp[k] = 0;
			memcpy(pos_tmp.direction, dir_tmp, 5*sizeof(int));
			push_pos(pos_tmp);

			info_tmp.pathlen = pathlen;
			info_tmp.direction = cur_dir;
			info_tmp.dir_cha_cnt = dir_change;
			push_info(info_tmp);

			if (k != cur_dir)
				dir_change++;
			cur_dir = k;
			switch (k) {
				case 1:{i--; break;}
				case 2:{j++; break;}
				case 3:{i++; break;}
				case 4:{j--; break;}
			}
			pathlen++;
			memset(dir_tmp, 0, sizeof(dir_tmp));
		}

		if (dir_change > 3 && top_pos != -1) //第一次初始化0
		{
			pos_tmp = pop_pos();
			i = pos_tmp.row;
			j = pos_tmp.col;

			info_tmp = pop_info();
			pathlen = info_tmp.pathlen;
			cur_dir = info_tmp.direction;
			dir_change = info_tmp.dir_cha_cnt;
		}
	}
	printf("%d\n", ++pathlen);
	return 0;
}


边写边改,代码有点乱,跑出结果就没有改了。。。上述代码中2个栈可以合为一个


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值