[置顶] 网易游戏在线笔试(电子数字+画线)

题目1 : 电子数字

时间限制: 10000ms
单点时限: 1000ms
内存限制: 256MB

描述

电子数字在生活中很常见,而许多的电子数字是由LED数码管制作而成。数字LED数码管一般由7个发光二极管封装在一起,组成'8'字型,引线在内部连接完成。如下图所示,我们可以对每个发光管进行编码从1到7。而数字0到数字9可以由这七根发光管的亮暗来表示。


[置顶] 网易游戏在线笔试(电子数字+画线)_第1张图片

假设我们现在有从左到右排列好的K个LED数码管,并且我们已知每个数码管当前有哪些编号的二极管是亮着的,另外剩余的二极管由于某些原因,我们并不清楚它们的亮暗情况。由于已经有部分二极管是确定亮着的,所以每个LED数码管能表示的数字范围会有所缩小,譬如假设1号二极管已经确定是亮着的状态,那么这个LED数码管就不能表示数字1和4。

我们想知道的是,给定一个数N,在这K个LED数码管的当前亮暗的状态下,所有可能表示的数中,比N小的数有多少个。

注意,前导0是必须的,假设有4个数码管的话,'0000'表示0,'0123'表示123,即每个数的表示方法唯一。

输入

每个输入数据包含多个测试点。

第一行为测试点的个数 S ≤ 100。之后是 S 个测试点的数据。测试点之间无空行。

每个测试点的第一行为 K(1 ≤ K ≤ 5)和N(0 ≤ N ≤ 109)。之后是K行,每行表示对应数码管已点亮的二极管的情况。每行至少包含一个数字,表示对应点亮的二极管的编号,即每个数码管至少有一根二极管是点亮的。二极管编号的范围保证在1到7之间,且每行无重复编号。

注意表示数码管点亮情况的每行数字之间以及行首行末之间可能存在冗余空格,每行的字符总长度不超过100。

输出

对于每个测试点,对应的结果输出一行,表示这K个数码管在当前状态下,所有可能表示的数中,比N小的数有多少个。

样例解释

第一个样例中,只有'020', '026', '028'符合要求。

第三个样例中,只有'000'符合要求。

样例输入
3
3 50
3  1
  1  4  5  
1   5  6 7
4 100
1 2 3
   4   5
6
  7  
1 1
  7


样例输出
3
0
1

#include <iostream>
#include <string>
using namespace std;

const int noNum[8][10] = {
	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
	{ 0, 1, 0, 0, 1, 0, 0, 0, 0, 0 },
	{ 0, 1, 1, 1, 0, 0, 0, 1, 0, 0 },
	{ 0, 0, 0, 0, 0, 1, 1, 0, 0, 0 },
	{ 1, 1, 0, 0, 0, 0, 0, 1, 0, 0 },
	{ 0, 1, 0, 1, 1, 1, 0, 1, 0, 1 },
	{ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
	{ 0, 1, 0, 0, 1, 0, 0, 1, 0, 0 }
};

int numSet[5][10];

const int max[] = { 1, 10, 100, 1000, 10000, 100000 };

//获取n的第i位数,从后往前模运算
int getBit(int n, int i, int k) {
	int rev = k - i - 1;
	while (rev--) {
		n /= 10;
	}
	return n % 10;
}

int main(void) {
	int S;
	cin >> S;
	while (S--) {
		memset(numSet, -1, sizeof(numSet));
		int K, N;
		cin >> K >> N;
		char ch;
		cin >> ch; //把上一个输入的 '\n' 读取完,否则
		for (int k = 0; k < K; ++k) {
			string line;
			cin >> line;
			for (int i = 0; i < line.length(); ++i) {
				if (line[i] != ' ') {
					for (int j = 0; j < 10; ++j) {
						if (1 == noNum[line[i] - '0'][j])
							numSet[k][j] = 0;
					}
				}
			}
		}

		int ans = 0;
		for (int i = 0; i < max[K] && i < N; ++i) {
			int j;
			for (j = 0; j < K; ++j) {
				if (0 == numSet[j][getBit(i, j, K)])
					break;
			}
			if (j == K)
				++ans;
		}
		cout << ans << endl;
	}
}



 

题目3 : 画线

时间限制: 10000ms
单点时限: 1000ms
内存限制: 256MB

描述

小王最近在开发一种新的游戏引擎,但是最近遇到了性能瓶颈。于是他打算从最基本的画线功能开始分析优化。画线其实就是调用一次drawline命令,根据给出的两端坐标,在屏幕画出对应的线段。但是小王发现,很多的drawline其实可以合并在一起,譬如下图中的线段(2,3)-(4,5)和线段(3,4)-(6,7),其实可以合并为一次drawline命令,直接画出线段(2,3)-(6,7)。当然有些线段是无法合并的,如线段(-3,8)-(1,8)和线段(3,8)-(6,8),就必须调用两次drawline命令。

[置顶] 网易游戏在线笔试(电子数字+画线)_第2张图片

画线示意图。注意颜色只是用于区分,实际线段都是黑色

给出N条drawline指令以及对应的线段坐标,小王想知道,实际最少用多少次drawline指令就可以画出来。

小王想先从最简单的情况开始分析优化,所以线段只包含四种情况:水平线段,垂直线段以及正反45度的线段。

输入

每个输入数据包含多个测试点。

第一行为测试点的个数 S ≤ 10。之后是 S 个测试点的数据。

每个测试点的第一行为 N(N ≤ 105)。之后是 N 行,每行包含4个整数:x0, y0, x1, y1,表示线段(x0,y0)-(x1,y1),坐标的范围在[-108, 108],保证线段的长度大于0。

输出

对于每个测试点,对应的结果输出一行,表示最少用多少次指令即可完成所有的画线。

样例输入
2
4
3 8 6 8
-3 8 1 8
2 3 4 5
3 4 6 7
5
1 1 2 2
2 2 3 3
3 3 4 2
4 2 5 1
1 0 100 0


样例输出
3
3

#include <iostream>
#include <vector>
using namespace std;

struct Line {
	int x1, y1, x2, y2;
};

//让每条直线都是呈现(x1, y1)在(x2, y2)左边,这样方便后面统一处理
void normal(Line &line) {
	if (line.x1 == line.x2) {
		if (line.y1 > line.y2)
			swap(line.y1, line.y2);
	}
	else if (line.x1 > line.x2) {
		swap(line.x1, line.x2);
		swap(line.y1, line.y2);
	}
}

//竖线比较函数
bool compa(const Line& line1, const Line& line2) {
	if (line1.x1 == line2.x1)
		return line1.y1 < line2.y1;
	else
		return line1.x1 < line2.x1;
}
//横线比较函数
bool compb(const Line& line1, const Line& line2) {
	if (line1.y1 == line2.y1)
		return line1.x1 < line2.x1;
	else
		return line1.y1 < line2.y1;
}
//正45度线比较函数
bool compc(const Line& line1, const Line& line2) {
	if (line1.y1 - line1.x1 == line2.y1 - line2.x1) //共线
		return line1.x1 < line2.x1;
	else
		return line1.y1 - line1.x1 < line.y1 - line.x1;
}
//反45度线比较函数
bool compd(const Line& line1, const Line& line2) {
	if (line1.y1 + line1.x1 == line2.y1 + line2.x1)
		return line1.x1 < line2.x1;
	else
		return line1.y1 + line1.x1 < line2.y1 + line2.x1;
}

int main(void) {
	int S;
	cin >> S;
	while (S--) {
		int N;
		cin >> N;
		vector<Line> a, b, c, d; //a存储竖线   b存储横线   c存储正45度线    d存储反45度线
		for (int i = 0; i < N; ++i) {
			Line line;
			cin >> line.x1 >> line.y1 >> line.x2 >> line.y2;
			
			//竖线
			if (line.x1 == line.x2)
				a.push_back(line);
			//横线
			else if (line.y1 == line.y2)
				b.push_back(line);
			//正45度线
			else if (line.y1 - line.x1 == line.y2 - line.x2)
				c.push_back(line);
			else
				d.push_back(line);
		}
		
		//以左右的排序规则,传入比较函数对每种类型的线集合排序
		sort(a.beign(), a.end(), compa);
		sort(b.begin(), b,end(), compb);
		sort(c.begin(), c.end(), compc);
		sort(d.begin(), d.end(), compd);
		
		int ans = 0;
		int temp;
		
		if (a.size() > 0) {
			++ans;
			temp = a[0].y2;
			for (int i = 1; i < a.size(); ++i) {
				if (a[i].x1 == a[i-1].x1 && a[i].y1 <= temp) {
					if (a[i].y2 > temp)
						temp = a[i].y2;
					continue;
				}
				else {
					++ans;
					temp = a[i].y2;
				}
			}
		}
		
		if (b.size() > 0) {
			++ans;
			temp = b[0].x2;
			for (int i = 1; i < b.size(); ++i) {
				if (b[i].y1 == b[i-1].y1 && b[i].x1 <= temp) {
					if (b[i].x2 > temp)
						temp = b[i].x2;
					continue;
				}
				else {
					++ans;
					temp = b[i].x2;
				}
			}
		}
		
		if (c.size() > 0) {
			++ans;
			temp = c[0].x2;
			for (int i = 1; i < c.size(); ++i) {
				if (c[i].y1 - c[i].x1 == c[i-1].y1 - c[i-1].x1 && c[i].x1 <= temp) {
					if (c[i].x2 > temp)
						temp = c[i].x2;
					continue;
				}
				else {
					++ans;
					temp = c[i].x2;
				}
			}
		}
		
		if (d.size() > 0) {
			++ans;
			temp = d[0].x2;
			for (int i = 1; i < d.size(); ++i) {
				if (d[i].y1 + d[i].x1 == d[i-1].y1 + d[i-1].x1 && d[i].x1 <= temp) {
					if (d[i].x2 > temp)
						temp = d[i].x2;
					continue;
				}
				else {
					++ans;
					temp = d[i].x2;
				}
			}
		}
		cout << ans << endl;
	}
}

你可能感兴趣的:(算法)