微软线上笔试-2015-4-3(1,2题) Magic Box && Professor Q's Software

写在前面:

http://blog.csdn.net/michael_kong_nju/article/details/44872519

关于4.3号的微软线上挑战赛,感觉自己还是刷题刷少了,表现在几个方面:1. 编程经验不足。2. 算法的使用不灵活。所以下面还是要加强OJ的训练,

把Leetcode上的题多做做。后面又把4道题仔细的编写调试了一下,希望和我情况类似的同学也能加紧代码的训练。

1. 第一题的原题是:

The circus clown Sunny has a magic box. When the circus is performing, Sunny puts some balls into the box one by one. The balls are in three colors: red(R), yellow(Y) and blue(B). Let Cr, Cy, Cb denote the numbers of red, yellow, blue balls in the box. Whenever the differences among Cr, Cy, Cb happen to be x, y, z, all balls in the box vanish. Given x, y, z and the sequence in which Sunny put the balls, you are to find what is the maximum number of balls in the box ever.

For example, let's assume x=1, y=2, z=3 and the sequence is RRYBRBRYBRY. After Sunny puts the first 7 balls, RRYBRBR, into the box, Cr, Cy, Cb are 4, 1, 2 respectively. The differences are exactly 1, 2, 3. (|Cr-Cy|=3, |Cy-Cb|=1, |Cb-Cr|=2) Then all the 7 balls vanish. Finally there are 4 balls in the box, after Sunny puts the remaining balls. So the box contains 7 balls at most, after Sunny puts the first 7 balls and before they vanish.

输入

Line 1: x y z

Line 2: the sequence consisting of only three characters 'R', 'Y' and 'B'.

For 30% data, the length of the sequence is no more than 200.

For 100% data, the length of the sequence is no more than 20,000, 0 <= x, y, z <= 20.

输出

The maximum number of balls in the box ever.

样例输入: 

1 2 3
RRYBRBRYBRY

样例输出:

7
其实这道题比较简单了,但是提交的时候总有些测试用例过不去,包括我自己刚开始的时候也是,最后因为实在找不出来也就没有继续下去。后面想了想大概是有下面几点需要注意的:

1. 因为球在一满足条件下会vanish,而这里的条件是选择性的精确匹配,即|cr-cy|可以等于1,2,3中的任意一个,而其另外两个的差值属于其它两个就可以了。

2. vanish在将所有的球都放进去的时候不止发生一次,所以要循环的去判断。

3. 有可能最后剩下的那个才是最大的,所以需要把所有的球都放完后将剩下的球和之前vanish的最大值做比较。

如果能够将上面所有的条件都考虑了应该就没有问题了,下面是具体的实现:

#include <iostream>         //by Lingtao Kong 2015/0404
#include <string>
#include <cmath>
void sort_int(int &r1, int &r2, int &r3)          //提前将x,y,z和差值进行排序就可以一次进行判断而不需要讨论了。
{
	if (r1 > r2)swap(r1, r2);
	if (r1 > r3)swap(r1, r3);
	if (r2 > r3)swap(r2, r3);
}
int print_max(int x, int y, int z, string box)
{
	sort_int(x, y, z); // to set x < y < z
	int red=0, blue=0, yello=0;
	int r1, r2, r3;
	int max = 0;
	int first = -1;
	for (int i = 0; i < box.size(); i++)
	{
		switch (box[i])
		{
		case 'R':
			red++; break;
		case 'Y':
			yello++; break;
		case 'B':
			blue++; break;
		default:
			break;
		}
		r1 = abs(red - blue);
	        r2 = abs(red - yello);
		r3 = abs(blue - yello); 
		sort_int(r1, r2, r3);
		if (r1 == x && r2 == y && r3 == z)
		{
			max = (i - first > max) ? (i - first) : max;          //使用的是下标的差值来计算个数的,有的同学使用的是三个球颜色之和也很好。
			first = i;
			red = 0;
			blue = 0;
			yello = 0;
		}
	}
	return (max > box.size()-1 - first) ? (max) : (box.size()-1 - first);   //和剩下的进行比较
}
void  main(void)
{
	int x, y, z;
	cin >> x >> y >> z;
	string ball;
	cin >> ball;
	cout << print_max(x, y, z, ball) << endl;
}

2. 第二道题

第二道题的题目比较复杂,如果你想看看英文我把他放在下面了:

描述

Professor Q develops a new software. The software consists of N modules which are numbered from 1 to N. The i-th module will be started up by signal Si. If signal Si is generated multiple times, the i-th module will also be started multiple times. Two different modules may be started up by the same signal. During its lifecircle, the i-th module will generate Ki signals: E1, E2, ..., EKi. These signals may start up other modules and so on. Fortunately the software is so carefully designed that there is no loop in the starting chain of modules, which means eventually all the modules will be stoped. Professor Q generates some initial signals and want to know how many times each module is started.

输入

The first line contains an integer T, the number of test cases. T test cases follows.

For each test case, the first line contains contains two numbers N and M, indicating the number of modules and number of signals that Professor Q generates initially.

The second line contains M integers, indicating the signals that Professor Q generates initially.

Line 3~N + 2, each line describes an module, following the format S, K, E1, E2, ... , EK. S represents the signal that start up this module. K represents the total amount of signals that are generated during the lifecircle of this module. And E1 ... EK are these signals.

For 20% data, all N, M <= 10
For 40% data, all N, M <= 103
For 100% data, all 1 <= T <= 5, N, M <= 105, 0 <= K <= 3, 0 <= S, E <= 105.

Hint: HUGE input in this problem. Fast IO such as scanf and BufferedReader are recommended.

输出

For each test case, output a line with N numbers Ans1, Ans2, ... , AnsN. Ansi is the number of times that the i-th module is started. In case the answers may be too large, output the answers modulo 142857 (the remainder of division by 142857).

样例输入
3
3 2
123 256
123 2 456 256
456 3 666 111 256
256 1 90
3 1
100
100 2 200 200
200 1 300
200 0
5 1
1
1 2 2 3
2 2 3 4
3 2 4 5
4 2 5 6
5 2 6 7
样例输出
1 1 3
1 2 2
1 1 2 3 5
其实这道题目的难点我认为有下面几个方面:

1. 对输入控制的要求较高,我们需要从控制台根据规范将所有的变量进行对应输入,同时还要进行相应大小变量的定义。

2. 对题目的变量的理解比较耗时,因为首先要把每个输入项搞懂。

如果对题目的意思很明白了,那么在有效的进行输入之后,设计算法就很简单了,只需要一个队列,然后将出队列的时候看激活的是哪个module并且将转换的数据

再次入队就可以了。下面是代码的实现,主要使用了动态数组以及queue数据结构。

注意: 我下面的是先读取所有的测试用例,然后再整个输出结果。如果是循环的,每一次一个用例输入然后每次一个输出,会简单许多,当然也是符合要求的。

/*
By Lingtao Kong 2015/04/04
*/
#include <iostream>
#include <queue>
using namespace std;
int N;  // 第一行输出的测试用例的数目
#define MAX_N 100010
#define MAX_M 100010
#define K 5  //每一行最多就只有5列,其中3个输出
int  (*modules_)[MAX_N][K];  //定义了一个动态的三维数组用来保存所有测试用例对应的转换模型。
int *modules_num, *signals_num;   //动态的数组用来保存每个测试用例对应的模块个数以及信号数量
int(*signals)[3];  //保存所有的输入输入的信号


/*从终端读入数据*/
void read_data()
{
	memset(modules_, -1, sizeof(modules_));
	for (int n = 0; n < N; n++)
	{


		cin >> modules_num[n] >> signals_num[n];   //输入第n个测试用例的 N M
		for (int i = 0; i < signals_num[n]; i++)
			cin >> signals[n][i];
		//输入第n个测试用例的第m个模块的对应的转换规则
		for (int m = 0; m < modules_num[n]; m++)  
		{
			cin >> modules_[n][m][0] >> modules_[n][m][1];   
			for (int e = 0; e < modules_[n][m][1]; e++)
				cin >> modules_[n][m][2 + e];
		}
	}
}
/*处理输出,对于每一个测试用例,将signals中的信号对应到刚才建立的模块中去*/
queue<int>qu_sig;
void process()
{
	for (int n = 0; n < N; n++)
	{
		//将初始信号装入队列。    
		for (int s = 0; s < signals_num[n]; s++)
		{
			qu_sig.push(signals[n][s]);
		}
		int *result = new int[modules_num[n]];
		memset(result, 0, sizeof(result)*modules_num[n]);
		int element;
		while (!qu_sig.empty())
		{
			element = qu_sig.front();
			for (int m = 0; m < modules_num[n]; m++)
			{
				if (element == modules_[n][m][0])
				{
					result[m]++;
					for (int e = 0; e < modules_[n][m][1]; e++)
						qu_sig.push(modules_[n][m][2 + e]);
				}
			}
			qu_sig.pop();
		}
		for (int i = 0; i < modules_num[n]; i++)
			cout << result[i] << " ";
		cout << endl;
		delete[]result;
	}
}
void main(void)
{
	cin >> N;
	modules_num = new int [N];
	signals_num = new int[N];
	signals = new int[N][3];
	modules_ = new int[N][MAX_N][K];
	read_data();
	process();
	delete[]modules_num;
	delete[]signals_num;
	delete[]signals;
	delete[]modules_;
}

限于篇幅在下一篇会给出第三,四题如果你发现有什么错误或者更好的算法欢迎批评指正。谢谢。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值